arbi 0.18.0__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.
Files changed (165) hide show
  1. arbi/__init__.py +92 -0
  2. arbi/_base_client.py +2124 -0
  3. arbi/_client.py +442 -0
  4. arbi/_compat.py +219 -0
  5. arbi/_constants.py +14 -0
  6. arbi/_exceptions.py +108 -0
  7. arbi/_files.py +123 -0
  8. arbi/_models.py +872 -0
  9. arbi/_qs.py +150 -0
  10. arbi/_resource.py +43 -0
  11. arbi/_response.py +830 -0
  12. arbi/_streaming.py +333 -0
  13. arbi/_types.py +270 -0
  14. arbi/_utils/__init__.py +64 -0
  15. arbi/_utils/_compat.py +45 -0
  16. arbi/_utils/_datetime_parse.py +136 -0
  17. arbi/_utils/_logs.py +25 -0
  18. arbi/_utils/_proxy.py +65 -0
  19. arbi/_utils/_reflection.py +42 -0
  20. arbi/_utils/_resources_proxy.py +24 -0
  21. arbi/_utils/_streams.py +12 -0
  22. arbi/_utils/_sync.py +58 -0
  23. arbi/_utils/_transform.py +457 -0
  24. arbi/_utils/_typing.py +156 -0
  25. arbi/_utils/_utils.py +421 -0
  26. arbi/_version.py +4 -0
  27. arbi/lib/.keep +4 -0
  28. arbi/py.typed +0 -0
  29. arbi/resources/__init__.py +19 -0
  30. arbi/resources/api/__init__.py +145 -0
  31. arbi/resources/api/api.py +422 -0
  32. arbi/resources/api/assistant.py +312 -0
  33. arbi/resources/api/configs.py +533 -0
  34. arbi/resources/api/conversation/__init__.py +33 -0
  35. arbi/resources/api/conversation/conversation.py +648 -0
  36. arbi/resources/api/conversation/user.py +270 -0
  37. arbi/resources/api/document/__init__.py +33 -0
  38. arbi/resources/api/document/doctag.py +516 -0
  39. arbi/resources/api/document/document.py +929 -0
  40. arbi/resources/api/health.py +253 -0
  41. arbi/resources/api/notifications.py +478 -0
  42. arbi/resources/api/tag.py +409 -0
  43. arbi/resources/api/user/__init__.py +61 -0
  44. arbi/resources/api/user/contacts.py +322 -0
  45. arbi/resources/api/user/settings.py +283 -0
  46. arbi/resources/api/user/subscription.py +230 -0
  47. arbi/resources/api/user/user.py +943 -0
  48. arbi/resources/api/workspace.py +1198 -0
  49. arbi/types/__init__.py +8 -0
  50. arbi/types/api/__init__.py +94 -0
  51. arbi/types/api/assistant_query_params.py +95 -0
  52. arbi/types/api/assistant_retrieve_params.py +95 -0
  53. arbi/types/api/chunker_config_param.py +9 -0
  54. arbi/types/api/config_create_params.py +227 -0
  55. arbi/types/api/config_create_response.py +17 -0
  56. arbi/types/api/config_delete_response.py +11 -0
  57. arbi/types/api/config_get_versions_response.py +19 -0
  58. arbi/types/api/config_retrieve_response.py +234 -0
  59. arbi/types/api/conversation/__init__.py +8 -0
  60. arbi/types/api/conversation/user_add_params.py +11 -0
  61. arbi/types/api/conversation/user_add_response.py +11 -0
  62. arbi/types/api/conversation/user_remove_params.py +11 -0
  63. arbi/types/api/conversation/user_remove_response.py +11 -0
  64. arbi/types/api/conversation_delete_message_response.py +11 -0
  65. arbi/types/api/conversation_delete_response.py +11 -0
  66. arbi/types/api/conversation_retrieve_message_response.py +105 -0
  67. arbi/types/api/conversation_retrieve_threads_response.py +124 -0
  68. arbi/types/api/conversation_share_response.py +11 -0
  69. arbi/types/api/conversation_update_title_params.py +16 -0
  70. arbi/types/api/conversation_update_title_response.py +13 -0
  71. arbi/types/api/doc_response.py +66 -0
  72. arbi/types/api/document/__init__.py +11 -0
  73. arbi/types/api/document/doc_tag_response.py +40 -0
  74. arbi/types/api/document/doctag_create_params.py +35 -0
  75. arbi/types/api/document/doctag_create_response.py +10 -0
  76. arbi/types/api/document/doctag_delete_params.py +15 -0
  77. arbi/types/api/document/doctag_generate_params.py +22 -0
  78. arbi/types/api/document/doctag_generate_response.py +20 -0
  79. arbi/types/api/document/doctag_update_params.py +35 -0
  80. arbi/types/api/document_date_extractor_llm_config.py +29 -0
  81. arbi/types/api/document_date_extractor_llm_config_param.py +28 -0
  82. arbi/types/api/document_delete_params.py +13 -0
  83. arbi/types/api/document_get_parsed_response.py +26 -0
  84. arbi/types/api/document_retrieve_params.py +16 -0
  85. arbi/types/api/document_retrieve_response.py +10 -0
  86. arbi/types/api/document_update_params.py +42 -0
  87. arbi/types/api/document_update_response.py +10 -0
  88. arbi/types/api/document_upload_from_url_params.py +26 -0
  89. arbi/types/api/document_upload_from_url_response.py +16 -0
  90. arbi/types/api/document_upload_params.py +26 -0
  91. arbi/types/api/document_upload_response.py +16 -0
  92. arbi/types/api/embedder_config.py +30 -0
  93. arbi/types/api/embedder_config_param.py +29 -0
  94. arbi/types/api/health_check_models_response.py +21 -0
  95. arbi/types/api/health_get_models_response.py +19 -0
  96. arbi/types/api/health_retrieve_status_response.py +49 -0
  97. arbi/types/api/model_citation_config.py +20 -0
  98. arbi/types/api/model_citation_config_param.py +20 -0
  99. arbi/types/api/notification_create_params.py +20 -0
  100. arbi/types/api/notification_create_response.py +47 -0
  101. arbi/types/api/notification_delete_params.py +13 -0
  102. arbi/types/api/notification_get_schemas_response.py +197 -0
  103. arbi/types/api/notification_list_response.py +47 -0
  104. arbi/types/api/notification_update_params.py +27 -0
  105. arbi/types/api/notification_update_response.py +47 -0
  106. arbi/types/api/parser_config_param.py +9 -0
  107. arbi/types/api/query_llm_config.py +30 -0
  108. arbi/types/api/query_llm_config_param.py +29 -0
  109. arbi/types/api/reranker_config.py +21 -0
  110. arbi/types/api/reranker_config_param.py +20 -0
  111. arbi/types/api/retriever_config.py +39 -0
  112. arbi/types/api/retriever_config_param.py +38 -0
  113. arbi/types/api/tag_create_params.py +49 -0
  114. arbi/types/api/tag_create_response.py +57 -0
  115. arbi/types/api/tag_delete_response.py +9 -0
  116. arbi/types/api/tag_update_params.py +22 -0
  117. arbi/types/api/tag_update_response.py +57 -0
  118. arbi/types/api/title_llm_config.py +29 -0
  119. arbi/types/api/title_llm_config_param.py +28 -0
  120. arbi/types/api/user/__init__.py +13 -0
  121. arbi/types/api/user/contact_create_params.py +13 -0
  122. arbi/types/api/user/contact_create_response.py +30 -0
  123. arbi/types/api/user/contact_delete_params.py +13 -0
  124. arbi/types/api/user/contact_list_response.py +30 -0
  125. arbi/types/api/user/setting_retrieve_response.py +89 -0
  126. arbi/types/api/user/setting_update_params.py +60 -0
  127. arbi/types/api/user/subscription_create_params.py +13 -0
  128. arbi/types/api/user/subscription_create_response.py +11 -0
  129. arbi/types/api/user/subscription_retrieve_response.py +48 -0
  130. arbi/types/api/user_change_password_params.py +18 -0
  131. arbi/types/api/user_change_password_response.py +11 -0
  132. arbi/types/api/user_check_sso_status_params.py +20 -0
  133. arbi/types/api/user_check_sso_status_response.py +25 -0
  134. arbi/types/api/user_list_products_response.py +37 -0
  135. arbi/types/api/user_list_workspaces_response.py +10 -0
  136. arbi/types/api/user_login_params.py +18 -0
  137. arbi/types/api/user_login_response.py +23 -0
  138. arbi/types/api/user_logout_response.py +9 -0
  139. arbi/types/api/user_register_params.py +22 -0
  140. arbi/types/api/user_response.py +26 -0
  141. arbi/types/api/user_verify_email_params.py +11 -0
  142. arbi/types/api/user_verify_email_response.py +9 -0
  143. arbi/types/api/workspace_copy_params.py +21 -0
  144. arbi/types/api/workspace_copy_response.py +25 -0
  145. arbi/types/api/workspace_create_protected_params.py +16 -0
  146. arbi/types/api/workspace_delete_response.py +9 -0
  147. arbi/types/api/workspace_get_conversations_response.py +30 -0
  148. arbi/types/api/workspace_get_documents_response.py +10 -0
  149. arbi/types/api/workspace_get_stats_response.py +17 -0
  150. arbi/types/api/workspace_get_tags_response.py +60 -0
  151. arbi/types/api/workspace_get_users_response.py +10 -0
  152. arbi/types/api/workspace_remove_user_params.py +11 -0
  153. arbi/types/api/workspace_remove_user_response.py +11 -0
  154. arbi/types/api/workspace_response.py +41 -0
  155. arbi/types/api/workspace_share_params.py +15 -0
  156. arbi/types/api/workspace_share_response.py +13 -0
  157. arbi/types/api/workspace_update_params.py +20 -0
  158. arbi/types/chunk.py +12 -0
  159. arbi/types/chunk_metadata.py +31 -0
  160. arbi/types/chunk_metadata_param.py +32 -0
  161. arbi/types/chunk_param.py +15 -0
  162. arbi-0.18.0.dist-info/METADATA +410 -0
  163. arbi-0.18.0.dist-info/RECORD +165 -0
  164. arbi-0.18.0.dist-info/WHEEL +4 -0
  165. arbi-0.18.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,943 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Dict, Optional
6
+
7
+ import httpx
8
+
9
+ from .contacts import (
10
+ ContactsResource,
11
+ AsyncContactsResource,
12
+ ContactsResourceWithRawResponse,
13
+ AsyncContactsResourceWithRawResponse,
14
+ ContactsResourceWithStreamingResponse,
15
+ AsyncContactsResourceWithStreamingResponse,
16
+ )
17
+ from .settings import (
18
+ SettingsResource,
19
+ AsyncSettingsResource,
20
+ SettingsResourceWithRawResponse,
21
+ AsyncSettingsResourceWithRawResponse,
22
+ SettingsResourceWithStreamingResponse,
23
+ AsyncSettingsResourceWithStreamingResponse,
24
+ )
25
+ from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
26
+ from ...._utils import maybe_transform, async_maybe_transform
27
+ from ...._compat import cached_property
28
+ from ...._resource import SyncAPIResource, AsyncAPIResource
29
+ from ...._response import (
30
+ to_raw_response_wrapper,
31
+ to_streamed_response_wrapper,
32
+ async_to_raw_response_wrapper,
33
+ async_to_streamed_response_wrapper,
34
+ )
35
+ from ....types.api import (
36
+ user_login_params,
37
+ user_register_params,
38
+ user_verify_email_params,
39
+ user_change_password_params,
40
+ user_check_sso_status_params,
41
+ )
42
+ from .subscription import (
43
+ SubscriptionResource,
44
+ AsyncSubscriptionResource,
45
+ SubscriptionResourceWithRawResponse,
46
+ AsyncSubscriptionResourceWithRawResponse,
47
+ SubscriptionResourceWithStreamingResponse,
48
+ AsyncSubscriptionResourceWithStreamingResponse,
49
+ )
50
+ from ...._base_client import make_request_options
51
+ from ....types.api.user_login_response import UserLoginResponse
52
+ from ....types.api.user_logout_response import UserLogoutResponse
53
+ from ....types.api.user_verify_email_response import UserVerifyEmailResponse
54
+ from ....types.api.user_list_products_response import UserListProductsResponse
55
+ from ....types.api.user_change_password_response import UserChangePasswordResponse
56
+ from ....types.api.user_list_workspaces_response import UserListWorkspacesResponse
57
+ from ....types.api.user_check_sso_status_response import UserCheckSSOStatusResponse
58
+
59
+ __all__ = ["UserResource", "AsyncUserResource"]
60
+
61
+
62
+ class UserResource(SyncAPIResource):
63
+ @cached_property
64
+ def settings(self) -> SettingsResource:
65
+ return SettingsResource(self._client)
66
+
67
+ @cached_property
68
+ def subscription(self) -> SubscriptionResource:
69
+ return SubscriptionResource(self._client)
70
+
71
+ @cached_property
72
+ def contacts(self) -> ContactsResource:
73
+ return ContactsResource(self._client)
74
+
75
+ @cached_property
76
+ def with_raw_response(self) -> UserResourceWithRawResponse:
77
+ """
78
+ This property can be used as a prefix for any HTTP method call to return
79
+ the raw response object instead of the parsed content.
80
+
81
+ For more information, see https://www.github.com/arbitrationcity/arbi-python#accessing-raw-response-data-eg-headers
82
+ """
83
+ return UserResourceWithRawResponse(self)
84
+
85
+ @cached_property
86
+ def with_streaming_response(self) -> UserResourceWithStreamingResponse:
87
+ """
88
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
89
+
90
+ For more information, see https://www.github.com/arbitrationcity/arbi-python#with_streaming_response
91
+ """
92
+ return UserResourceWithStreamingResponse(self)
93
+
94
+ def change_password(
95
+ self,
96
+ *,
97
+ new_signing_key: str,
98
+ rewrapped_workspace_keys: Dict[str, str],
99
+ signature: str,
100
+ timestamp: int,
101
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
102
+ # The extra values given here take precedence over values defined on the client or passed to this method.
103
+ extra_headers: Headers | None = None,
104
+ extra_query: Query | None = None,
105
+ extra_body: Body | None = None,
106
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
107
+ ) -> UserChangePasswordResponse:
108
+ """Change user's master password by re-keying all workspace keys.
109
+
110
+ Client must:
111
+
112
+ 1.
113
+
114
+ Sign "email|timestamp" with current Ed25519 key (proves current password)
115
+ 2. Provide new Ed25519 signing key (derived from new password)
116
+ 3. Re-wrap all workspace keys with new X25519 public key
117
+
118
+ Server will:
119
+
120
+ 1. Verify signature with stored signing_key_pub
121
+ 2. Derive new X25519 encryption key from new Ed25519 signing key
122
+ 3. Update both keys and all workspace wrapped keys
123
+
124
+ Note: This changes the master password (encryption password), not authentication
125
+ password. Both local and SSO users can change their master password.
126
+
127
+ Args:
128
+ extra_headers: Send extra headers
129
+
130
+ extra_query: Add additional query parameters to the request
131
+
132
+ extra_body: Add additional JSON properties to the request
133
+
134
+ timeout: Override the client-level default timeout for this request, in seconds
135
+ """
136
+ return self._post(
137
+ "/api/user/change_password",
138
+ body=maybe_transform(
139
+ {
140
+ "new_signing_key": new_signing_key,
141
+ "rewrapped_workspace_keys": rewrapped_workspace_keys,
142
+ "signature": signature,
143
+ "timestamp": timestamp,
144
+ },
145
+ user_change_password_params.UserChangePasswordParams,
146
+ ),
147
+ options=make_request_options(
148
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
149
+ ),
150
+ cast_to=UserChangePasswordResponse,
151
+ )
152
+
153
+ def check_sso_status(
154
+ self,
155
+ *,
156
+ email: str,
157
+ sso_token: str,
158
+ family_name: Optional[str] | Omit = omit,
159
+ given_name: Optional[str] | Omit = omit,
160
+ picture: Optional[str] | Omit = omit,
161
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
162
+ # The extra values given here take precedence over values defined on the client or passed to this method.
163
+ extra_headers: Headers | None = None,
164
+ extra_query: Query | None = None,
165
+ extra_body: Body | None = None,
166
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
167
+ ) -> UserCheckSSOStatusResponse:
168
+ """Check SSO user registration state.
169
+
170
+ Returns one of three states:
171
+
172
+ 1.
173
+
174
+ new_user: No user exists with this email
175
+ 2. local_exists: User exists but registered locally (can link to SSO)
176
+ 3. sso_exists: User exists and already linked to SSO
177
+
178
+ Frontend uses this to show appropriate UI:
179
+
180
+ - new_user -> "Set Master Password"
181
+ - local_exists -> "Link SSO? Enter current master password"
182
+ - sso_exists -> "Enter Master Password"
183
+
184
+ Args:
185
+ extra_headers: Send extra headers
186
+
187
+ extra_query: Add additional query parameters to the request
188
+
189
+ extra_body: Add additional JSON properties to the request
190
+
191
+ timeout: Override the client-level default timeout for this request, in seconds
192
+ """
193
+ return self._post(
194
+ "/api/user/sso-status",
195
+ body=maybe_transform(
196
+ {
197
+ "email": email,
198
+ "sso_token": sso_token,
199
+ "family_name": family_name,
200
+ "given_name": given_name,
201
+ "picture": picture,
202
+ },
203
+ user_check_sso_status_params.UserCheckSSOStatusParams,
204
+ ),
205
+ options=make_request_options(
206
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
207
+ ),
208
+ cast_to=UserCheckSSOStatusResponse,
209
+ )
210
+
211
+ def list_products(
212
+ self,
213
+ *,
214
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
215
+ # The extra values given here take precedence over values defined on the client or passed to this method.
216
+ extra_headers: Headers | None = None,
217
+ extra_query: Query | None = None,
218
+ extra_body: Body | None = None,
219
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
220
+ ) -> UserListProductsResponse:
221
+ """Get available subscription products and prices from Stripe."""
222
+ return self._get(
223
+ "/api/user/products",
224
+ options=make_request_options(
225
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
226
+ ),
227
+ cast_to=UserListProductsResponse,
228
+ )
229
+
230
+ def list_workspaces(
231
+ self,
232
+ *,
233
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
234
+ # The extra values given here take precedence over values defined on the client or passed to this method.
235
+ extra_headers: Headers | None = None,
236
+ extra_query: Query | None = None,
237
+ extra_body: Body | None = None,
238
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
239
+ ) -> UserListWorkspacesResponse:
240
+ """
241
+ Retrieve the list of workspaces associated with the current authenticated user.
242
+ Includes wrapped_key, stats (conversation/document counts with shared/private
243
+ breakdown), and users for each workspace. All data is fetched efficiently using
244
+ batch queries to avoid N+1 problems. Leverages RLS to enforce access control.
245
+ """
246
+ return self._get(
247
+ "/api/user/workspaces",
248
+ options=make_request_options(
249
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
250
+ ),
251
+ cast_to=UserListWorkspacesResponse,
252
+ )
253
+
254
+ def login(
255
+ self,
256
+ *,
257
+ email: str,
258
+ signature: str,
259
+ timestamp: int,
260
+ sso_token: Optional[str] | Omit = omit,
261
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
262
+ # The extra values given here take precedence over values defined on the client or passed to this method.
263
+ extra_headers: Headers | None = None,
264
+ extra_query: Query | None = None,
265
+ extra_body: Body | None = None,
266
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
267
+ ) -> UserLoginResponse:
268
+ """
269
+ Login with Ed25519 signature verification (local or SSO).
270
+
271
+ Authentication flow:
272
+
273
+ 1. Client derives Ed25519 keypair from password
274
+ 2. Client signs "email|timestamp" with Ed25519 private key
275
+ 3. Server verifies signature using stored Ed25519 public key
276
+ 4. Server encrypts response with stored X25519 public key
277
+
278
+ For SSO users: Also validates SSO token before proceeding.
279
+
280
+ Returns encrypted login response that only the correct password can decrypt.
281
+
282
+ Args:
283
+ extra_headers: Send extra headers
284
+
285
+ extra_query: Add additional query parameters to the request
286
+
287
+ extra_body: Add additional JSON properties to the request
288
+
289
+ timeout: Override the client-level default timeout for this request, in seconds
290
+ """
291
+ return self._post(
292
+ "/api/user/login",
293
+ body=maybe_transform(
294
+ {
295
+ "email": email,
296
+ "signature": signature,
297
+ "timestamp": timestamp,
298
+ "sso_token": sso_token,
299
+ },
300
+ user_login_params.UserLoginParams,
301
+ ),
302
+ options=make_request_options(
303
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
304
+ ),
305
+ cast_to=UserLoginResponse,
306
+ )
307
+
308
+ def logout(
309
+ self,
310
+ *,
311
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
312
+ # The extra values given here take precedence over values defined on the client or passed to this method.
313
+ extra_headers: Headers | None = None,
314
+ extra_query: Query | None = None,
315
+ extra_body: Body | None = None,
316
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
317
+ ) -> UserLogoutResponse:
318
+ """Log out the current user by clearing the refresh token cookie and session key."""
319
+ return self._post(
320
+ "/api/user/logout",
321
+ options=make_request_options(
322
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
323
+ ),
324
+ cast_to=UserLogoutResponse,
325
+ )
326
+
327
+ def register(
328
+ self,
329
+ *,
330
+ email: str,
331
+ signing_key: str,
332
+ verification_credential: str,
333
+ family_name: Optional[str] | Omit = omit,
334
+ given_name: Optional[str] | Omit = omit,
335
+ picture: Optional[str] | Omit = omit,
336
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
337
+ # The extra values given here take precedence over values defined on the client or passed to this method.
338
+ extra_headers: Headers | None = None,
339
+ extra_query: Query | None = None,
340
+ extra_body: Body | None = None,
341
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
342
+ ) -> object:
343
+ """
344
+ Register a new user with email verification (local or SSO).
345
+
346
+ Accepts either:
347
+
348
+ - 3-word verification code for local users
349
+ - SSO JWT token for SSO users
350
+
351
+ Auto-detects credential type and handles both flows.
352
+
353
+ Args:
354
+ extra_headers: Send extra headers
355
+
356
+ extra_query: Add additional query parameters to the request
357
+
358
+ extra_body: Add additional JSON properties to the request
359
+
360
+ timeout: Override the client-level default timeout for this request, in seconds
361
+ """
362
+ return self._post(
363
+ "/api/user/register",
364
+ body=maybe_transform(
365
+ {
366
+ "email": email,
367
+ "signing_key": signing_key,
368
+ "verification_credential": verification_credential,
369
+ "family_name": family_name,
370
+ "given_name": given_name,
371
+ "picture": picture,
372
+ },
373
+ user_register_params.UserRegisterParams,
374
+ ),
375
+ options=make_request_options(
376
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
377
+ ),
378
+ cast_to=object,
379
+ )
380
+
381
+ def verify_email(
382
+ self,
383
+ *,
384
+ email: str,
385
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
386
+ # The extra values given here take precedence over values defined on the client or passed to this method.
387
+ extra_headers: Headers | None = None,
388
+ extra_query: Query | None = None,
389
+ extra_body: Body | None = None,
390
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
391
+ ) -> UserVerifyEmailResponse:
392
+ """Send verification email with 3-word code to user.
393
+
394
+ Calls central server to send
395
+ the email.
396
+
397
+ Note: Fails silently if email already exists to prevent email enumeration
398
+ attacks. Also returns success even on rate limit/errors to avoid information
399
+ disclosure.
400
+
401
+ Args:
402
+ extra_headers: Send extra headers
403
+
404
+ extra_query: Add additional query parameters to the request
405
+
406
+ extra_body: Add additional JSON properties to the request
407
+
408
+ timeout: Override the client-level default timeout for this request, in seconds
409
+ """
410
+ return self._post(
411
+ "/api/user/verify-email",
412
+ body=maybe_transform({"email": email}, user_verify_email_params.UserVerifyEmailParams),
413
+ options=make_request_options(
414
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
415
+ ),
416
+ cast_to=UserVerifyEmailResponse,
417
+ )
418
+
419
+
420
+ class AsyncUserResource(AsyncAPIResource):
421
+ @cached_property
422
+ def settings(self) -> AsyncSettingsResource:
423
+ return AsyncSettingsResource(self._client)
424
+
425
+ @cached_property
426
+ def subscription(self) -> AsyncSubscriptionResource:
427
+ return AsyncSubscriptionResource(self._client)
428
+
429
+ @cached_property
430
+ def contacts(self) -> AsyncContactsResource:
431
+ return AsyncContactsResource(self._client)
432
+
433
+ @cached_property
434
+ def with_raw_response(self) -> AsyncUserResourceWithRawResponse:
435
+ """
436
+ This property can be used as a prefix for any HTTP method call to return
437
+ the raw response object instead of the parsed content.
438
+
439
+ For more information, see https://www.github.com/arbitrationcity/arbi-python#accessing-raw-response-data-eg-headers
440
+ """
441
+ return AsyncUserResourceWithRawResponse(self)
442
+
443
+ @cached_property
444
+ def with_streaming_response(self) -> AsyncUserResourceWithStreamingResponse:
445
+ """
446
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
447
+
448
+ For more information, see https://www.github.com/arbitrationcity/arbi-python#with_streaming_response
449
+ """
450
+ return AsyncUserResourceWithStreamingResponse(self)
451
+
452
+ async def change_password(
453
+ self,
454
+ *,
455
+ new_signing_key: str,
456
+ rewrapped_workspace_keys: Dict[str, str],
457
+ signature: str,
458
+ timestamp: int,
459
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
460
+ # The extra values given here take precedence over values defined on the client or passed to this method.
461
+ extra_headers: Headers | None = None,
462
+ extra_query: Query | None = None,
463
+ extra_body: Body | None = None,
464
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
465
+ ) -> UserChangePasswordResponse:
466
+ """Change user's master password by re-keying all workspace keys.
467
+
468
+ Client must:
469
+
470
+ 1.
471
+
472
+ Sign "email|timestamp" with current Ed25519 key (proves current password)
473
+ 2. Provide new Ed25519 signing key (derived from new password)
474
+ 3. Re-wrap all workspace keys with new X25519 public key
475
+
476
+ Server will:
477
+
478
+ 1. Verify signature with stored signing_key_pub
479
+ 2. Derive new X25519 encryption key from new Ed25519 signing key
480
+ 3. Update both keys and all workspace wrapped keys
481
+
482
+ Note: This changes the master password (encryption password), not authentication
483
+ password. Both local and SSO users can change their master password.
484
+
485
+ Args:
486
+ extra_headers: Send extra headers
487
+
488
+ extra_query: Add additional query parameters to the request
489
+
490
+ extra_body: Add additional JSON properties to the request
491
+
492
+ timeout: Override the client-level default timeout for this request, in seconds
493
+ """
494
+ return await self._post(
495
+ "/api/user/change_password",
496
+ body=await async_maybe_transform(
497
+ {
498
+ "new_signing_key": new_signing_key,
499
+ "rewrapped_workspace_keys": rewrapped_workspace_keys,
500
+ "signature": signature,
501
+ "timestamp": timestamp,
502
+ },
503
+ user_change_password_params.UserChangePasswordParams,
504
+ ),
505
+ options=make_request_options(
506
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
507
+ ),
508
+ cast_to=UserChangePasswordResponse,
509
+ )
510
+
511
+ async def check_sso_status(
512
+ self,
513
+ *,
514
+ email: str,
515
+ sso_token: str,
516
+ family_name: Optional[str] | Omit = omit,
517
+ given_name: Optional[str] | Omit = omit,
518
+ picture: Optional[str] | Omit = omit,
519
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
520
+ # The extra values given here take precedence over values defined on the client or passed to this method.
521
+ extra_headers: Headers | None = None,
522
+ extra_query: Query | None = None,
523
+ extra_body: Body | None = None,
524
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
525
+ ) -> UserCheckSSOStatusResponse:
526
+ """Check SSO user registration state.
527
+
528
+ Returns one of three states:
529
+
530
+ 1.
531
+
532
+ new_user: No user exists with this email
533
+ 2. local_exists: User exists but registered locally (can link to SSO)
534
+ 3. sso_exists: User exists and already linked to SSO
535
+
536
+ Frontend uses this to show appropriate UI:
537
+
538
+ - new_user -> "Set Master Password"
539
+ - local_exists -> "Link SSO? Enter current master password"
540
+ - sso_exists -> "Enter Master Password"
541
+
542
+ Args:
543
+ extra_headers: Send extra headers
544
+
545
+ extra_query: Add additional query parameters to the request
546
+
547
+ extra_body: Add additional JSON properties to the request
548
+
549
+ timeout: Override the client-level default timeout for this request, in seconds
550
+ """
551
+ return await self._post(
552
+ "/api/user/sso-status",
553
+ body=await async_maybe_transform(
554
+ {
555
+ "email": email,
556
+ "sso_token": sso_token,
557
+ "family_name": family_name,
558
+ "given_name": given_name,
559
+ "picture": picture,
560
+ },
561
+ user_check_sso_status_params.UserCheckSSOStatusParams,
562
+ ),
563
+ options=make_request_options(
564
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
565
+ ),
566
+ cast_to=UserCheckSSOStatusResponse,
567
+ )
568
+
569
+ async def list_products(
570
+ self,
571
+ *,
572
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
573
+ # The extra values given here take precedence over values defined on the client or passed to this method.
574
+ extra_headers: Headers | None = None,
575
+ extra_query: Query | None = None,
576
+ extra_body: Body | None = None,
577
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
578
+ ) -> UserListProductsResponse:
579
+ """Get available subscription products and prices from Stripe."""
580
+ return await self._get(
581
+ "/api/user/products",
582
+ options=make_request_options(
583
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
584
+ ),
585
+ cast_to=UserListProductsResponse,
586
+ )
587
+
588
+ async def list_workspaces(
589
+ self,
590
+ *,
591
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
592
+ # The extra values given here take precedence over values defined on the client or passed to this method.
593
+ extra_headers: Headers | None = None,
594
+ extra_query: Query | None = None,
595
+ extra_body: Body | None = None,
596
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
597
+ ) -> UserListWorkspacesResponse:
598
+ """
599
+ Retrieve the list of workspaces associated with the current authenticated user.
600
+ Includes wrapped_key, stats (conversation/document counts with shared/private
601
+ breakdown), and users for each workspace. All data is fetched efficiently using
602
+ batch queries to avoid N+1 problems. Leverages RLS to enforce access control.
603
+ """
604
+ return await self._get(
605
+ "/api/user/workspaces",
606
+ options=make_request_options(
607
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
608
+ ),
609
+ cast_to=UserListWorkspacesResponse,
610
+ )
611
+
612
+ async def login(
613
+ self,
614
+ *,
615
+ email: str,
616
+ signature: str,
617
+ timestamp: int,
618
+ sso_token: Optional[str] | Omit = omit,
619
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
620
+ # The extra values given here take precedence over values defined on the client or passed to this method.
621
+ extra_headers: Headers | None = None,
622
+ extra_query: Query | None = None,
623
+ extra_body: Body | None = None,
624
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
625
+ ) -> UserLoginResponse:
626
+ """
627
+ Login with Ed25519 signature verification (local or SSO).
628
+
629
+ Authentication flow:
630
+
631
+ 1. Client derives Ed25519 keypair from password
632
+ 2. Client signs "email|timestamp" with Ed25519 private key
633
+ 3. Server verifies signature using stored Ed25519 public key
634
+ 4. Server encrypts response with stored X25519 public key
635
+
636
+ For SSO users: Also validates SSO token before proceeding.
637
+
638
+ Returns encrypted login response that only the correct password can decrypt.
639
+
640
+ Args:
641
+ extra_headers: Send extra headers
642
+
643
+ extra_query: Add additional query parameters to the request
644
+
645
+ extra_body: Add additional JSON properties to the request
646
+
647
+ timeout: Override the client-level default timeout for this request, in seconds
648
+ """
649
+ return await self._post(
650
+ "/api/user/login",
651
+ body=await async_maybe_transform(
652
+ {
653
+ "email": email,
654
+ "signature": signature,
655
+ "timestamp": timestamp,
656
+ "sso_token": sso_token,
657
+ },
658
+ user_login_params.UserLoginParams,
659
+ ),
660
+ options=make_request_options(
661
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
662
+ ),
663
+ cast_to=UserLoginResponse,
664
+ )
665
+
666
+ async def logout(
667
+ self,
668
+ *,
669
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
670
+ # The extra values given here take precedence over values defined on the client or passed to this method.
671
+ extra_headers: Headers | None = None,
672
+ extra_query: Query | None = None,
673
+ extra_body: Body | None = None,
674
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
675
+ ) -> UserLogoutResponse:
676
+ """Log out the current user by clearing the refresh token cookie and session key."""
677
+ return await self._post(
678
+ "/api/user/logout",
679
+ options=make_request_options(
680
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
681
+ ),
682
+ cast_to=UserLogoutResponse,
683
+ )
684
+
685
+ async def register(
686
+ self,
687
+ *,
688
+ email: str,
689
+ signing_key: str,
690
+ verification_credential: str,
691
+ family_name: Optional[str] | Omit = omit,
692
+ given_name: Optional[str] | Omit = omit,
693
+ picture: Optional[str] | Omit = omit,
694
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
695
+ # The extra values given here take precedence over values defined on the client or passed to this method.
696
+ extra_headers: Headers | None = None,
697
+ extra_query: Query | None = None,
698
+ extra_body: Body | None = None,
699
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
700
+ ) -> object:
701
+ """
702
+ Register a new user with email verification (local or SSO).
703
+
704
+ Accepts either:
705
+
706
+ - 3-word verification code for local users
707
+ - SSO JWT token for SSO users
708
+
709
+ Auto-detects credential type and handles both flows.
710
+
711
+ Args:
712
+ extra_headers: Send extra headers
713
+
714
+ extra_query: Add additional query parameters to the request
715
+
716
+ extra_body: Add additional JSON properties to the request
717
+
718
+ timeout: Override the client-level default timeout for this request, in seconds
719
+ """
720
+ return await self._post(
721
+ "/api/user/register",
722
+ body=await async_maybe_transform(
723
+ {
724
+ "email": email,
725
+ "signing_key": signing_key,
726
+ "verification_credential": verification_credential,
727
+ "family_name": family_name,
728
+ "given_name": given_name,
729
+ "picture": picture,
730
+ },
731
+ user_register_params.UserRegisterParams,
732
+ ),
733
+ options=make_request_options(
734
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
735
+ ),
736
+ cast_to=object,
737
+ )
738
+
739
+ async def verify_email(
740
+ self,
741
+ *,
742
+ email: str,
743
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
744
+ # The extra values given here take precedence over values defined on the client or passed to this method.
745
+ extra_headers: Headers | None = None,
746
+ extra_query: Query | None = None,
747
+ extra_body: Body | None = None,
748
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
749
+ ) -> UserVerifyEmailResponse:
750
+ """Send verification email with 3-word code to user.
751
+
752
+ Calls central server to send
753
+ the email.
754
+
755
+ Note: Fails silently if email already exists to prevent email enumeration
756
+ attacks. Also returns success even on rate limit/errors to avoid information
757
+ disclosure.
758
+
759
+ Args:
760
+ extra_headers: Send extra headers
761
+
762
+ extra_query: Add additional query parameters to the request
763
+
764
+ extra_body: Add additional JSON properties to the request
765
+
766
+ timeout: Override the client-level default timeout for this request, in seconds
767
+ """
768
+ return await self._post(
769
+ "/api/user/verify-email",
770
+ body=await async_maybe_transform({"email": email}, user_verify_email_params.UserVerifyEmailParams),
771
+ options=make_request_options(
772
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
773
+ ),
774
+ cast_to=UserVerifyEmailResponse,
775
+ )
776
+
777
+
778
+ class UserResourceWithRawResponse:
779
+ def __init__(self, user: UserResource) -> None:
780
+ self._user = user
781
+
782
+ self.change_password = to_raw_response_wrapper(
783
+ user.change_password,
784
+ )
785
+ self.check_sso_status = to_raw_response_wrapper(
786
+ user.check_sso_status,
787
+ )
788
+ self.list_products = to_raw_response_wrapper(
789
+ user.list_products,
790
+ )
791
+ self.list_workspaces = to_raw_response_wrapper(
792
+ user.list_workspaces,
793
+ )
794
+ self.login = to_raw_response_wrapper(
795
+ user.login,
796
+ )
797
+ self.logout = to_raw_response_wrapper(
798
+ user.logout,
799
+ )
800
+ self.register = to_raw_response_wrapper(
801
+ user.register,
802
+ )
803
+ self.verify_email = to_raw_response_wrapper(
804
+ user.verify_email,
805
+ )
806
+
807
+ @cached_property
808
+ def settings(self) -> SettingsResourceWithRawResponse:
809
+ return SettingsResourceWithRawResponse(self._user.settings)
810
+
811
+ @cached_property
812
+ def subscription(self) -> SubscriptionResourceWithRawResponse:
813
+ return SubscriptionResourceWithRawResponse(self._user.subscription)
814
+
815
+ @cached_property
816
+ def contacts(self) -> ContactsResourceWithRawResponse:
817
+ return ContactsResourceWithRawResponse(self._user.contacts)
818
+
819
+
820
+ class AsyncUserResourceWithRawResponse:
821
+ def __init__(self, user: AsyncUserResource) -> None:
822
+ self._user = user
823
+
824
+ self.change_password = async_to_raw_response_wrapper(
825
+ user.change_password,
826
+ )
827
+ self.check_sso_status = async_to_raw_response_wrapper(
828
+ user.check_sso_status,
829
+ )
830
+ self.list_products = async_to_raw_response_wrapper(
831
+ user.list_products,
832
+ )
833
+ self.list_workspaces = async_to_raw_response_wrapper(
834
+ user.list_workspaces,
835
+ )
836
+ self.login = async_to_raw_response_wrapper(
837
+ user.login,
838
+ )
839
+ self.logout = async_to_raw_response_wrapper(
840
+ user.logout,
841
+ )
842
+ self.register = async_to_raw_response_wrapper(
843
+ user.register,
844
+ )
845
+ self.verify_email = async_to_raw_response_wrapper(
846
+ user.verify_email,
847
+ )
848
+
849
+ @cached_property
850
+ def settings(self) -> AsyncSettingsResourceWithRawResponse:
851
+ return AsyncSettingsResourceWithRawResponse(self._user.settings)
852
+
853
+ @cached_property
854
+ def subscription(self) -> AsyncSubscriptionResourceWithRawResponse:
855
+ return AsyncSubscriptionResourceWithRawResponse(self._user.subscription)
856
+
857
+ @cached_property
858
+ def contacts(self) -> AsyncContactsResourceWithRawResponse:
859
+ return AsyncContactsResourceWithRawResponse(self._user.contacts)
860
+
861
+
862
+ class UserResourceWithStreamingResponse:
863
+ def __init__(self, user: UserResource) -> None:
864
+ self._user = user
865
+
866
+ self.change_password = to_streamed_response_wrapper(
867
+ user.change_password,
868
+ )
869
+ self.check_sso_status = to_streamed_response_wrapper(
870
+ user.check_sso_status,
871
+ )
872
+ self.list_products = to_streamed_response_wrapper(
873
+ user.list_products,
874
+ )
875
+ self.list_workspaces = to_streamed_response_wrapper(
876
+ user.list_workspaces,
877
+ )
878
+ self.login = to_streamed_response_wrapper(
879
+ user.login,
880
+ )
881
+ self.logout = to_streamed_response_wrapper(
882
+ user.logout,
883
+ )
884
+ self.register = to_streamed_response_wrapper(
885
+ user.register,
886
+ )
887
+ self.verify_email = to_streamed_response_wrapper(
888
+ user.verify_email,
889
+ )
890
+
891
+ @cached_property
892
+ def settings(self) -> SettingsResourceWithStreamingResponse:
893
+ return SettingsResourceWithStreamingResponse(self._user.settings)
894
+
895
+ @cached_property
896
+ def subscription(self) -> SubscriptionResourceWithStreamingResponse:
897
+ return SubscriptionResourceWithStreamingResponse(self._user.subscription)
898
+
899
+ @cached_property
900
+ def contacts(self) -> ContactsResourceWithStreamingResponse:
901
+ return ContactsResourceWithStreamingResponse(self._user.contacts)
902
+
903
+
904
+ class AsyncUserResourceWithStreamingResponse:
905
+ def __init__(self, user: AsyncUserResource) -> None:
906
+ self._user = user
907
+
908
+ self.change_password = async_to_streamed_response_wrapper(
909
+ user.change_password,
910
+ )
911
+ self.check_sso_status = async_to_streamed_response_wrapper(
912
+ user.check_sso_status,
913
+ )
914
+ self.list_products = async_to_streamed_response_wrapper(
915
+ user.list_products,
916
+ )
917
+ self.list_workspaces = async_to_streamed_response_wrapper(
918
+ user.list_workspaces,
919
+ )
920
+ self.login = async_to_streamed_response_wrapper(
921
+ user.login,
922
+ )
923
+ self.logout = async_to_streamed_response_wrapper(
924
+ user.logout,
925
+ )
926
+ self.register = async_to_streamed_response_wrapper(
927
+ user.register,
928
+ )
929
+ self.verify_email = async_to_streamed_response_wrapper(
930
+ user.verify_email,
931
+ )
932
+
933
+ @cached_property
934
+ def settings(self) -> AsyncSettingsResourceWithStreamingResponse:
935
+ return AsyncSettingsResourceWithStreamingResponse(self._user.settings)
936
+
937
+ @cached_property
938
+ def subscription(self) -> AsyncSubscriptionResourceWithStreamingResponse:
939
+ return AsyncSubscriptionResourceWithStreamingResponse(self._user.subscription)
940
+
941
+ @cached_property
942
+ def contacts(self) -> AsyncContactsResourceWithStreamingResponse:
943
+ return AsyncContactsResourceWithStreamingResponse(self._user.contacts)