arbi 0.2.0__py3-none-any.whl → 0.3.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.

Potentially problematic release.


This version of arbi might be problematic. Click here for more details.

Files changed (47) hide show
  1. arbi/_streaming.py +4 -6
  2. arbi/_version.py +1 -1
  3. arbi/resources/api/__init__.py +0 -14
  4. arbi/resources/api/api.py +0 -32
  5. arbi/resources/api/assistant.py +9 -1
  6. arbi/resources/api/conversation/conversation.py +87 -2
  7. arbi/resources/api/document/annotation.py +9 -1
  8. arbi/resources/api/document/document.py +39 -1
  9. arbi/resources/api/tag.py +13 -1
  10. arbi/resources/api/user/user.py +397 -134
  11. arbi/resources/api/workspace.py +202 -12
  12. arbi/types/api/__init__.py +12 -7
  13. arbi/types/api/assistant_query_params.py +22 -2
  14. arbi/types/api/assistant_retrieve_params.py +22 -2
  15. arbi/types/api/conversation_retrieve_message_response.py +99 -0
  16. arbi/types/api/conversation_retrieve_threads_response.py +16 -0
  17. arbi/types/api/document/annotation_create_params.py +5 -1
  18. arbi/types/api/document/annotation_update_params.py +5 -1
  19. arbi/types/api/document_update_params.py +2 -0
  20. arbi/types/api/document_upload_from_url_params.py +4 -1
  21. arbi/types/api/document_upload_params.py +4 -1
  22. arbi/types/api/document_view_params.py +5 -1
  23. arbi/types/api/tag_create_params.py +5 -1
  24. arbi/types/api/tag_update_params.py +5 -1
  25. arbi/types/api/user_change_password_params.py +16 -0
  26. arbi/types/api/{sso_rotate_passcode_response.py → user_change_password_response.py} +3 -3
  27. arbi/types/api/{sso_login_params.py → user_check_sso_status_params.py} +3 -6
  28. arbi/types/api/{user_response.py → user_check_sso_status_response.py} +4 -6
  29. arbi/types/api/{sso_invite_params.py → user_invite_params.py} +2 -2
  30. arbi/types/api/{sso_invite_response.py → user_invite_response.py} +2 -4
  31. arbi/types/api/user_login_params.py +4 -1
  32. arbi/types/api/user_login_response.py +8 -0
  33. arbi/types/api/user_register_params.py +5 -4
  34. arbi/types/api/workspace_copy_params.py +21 -0
  35. arbi/types/api/workspace_copy_response.py +25 -0
  36. arbi/types/api/workspace_get_stats_response.py +6 -2
  37. arbi/types/api/workspace_get_users_response.py +5 -1
  38. arbi/types/api/workspace_response.py +24 -2
  39. arbi/types/api/workspace_share_params.py +5 -1
  40. arbi/types/api/workspace_update_params.py +5 -1
  41. {arbi-0.2.0.dist-info → arbi-0.3.0.dist-info}/METADATA +2 -2
  42. {arbi-0.2.0.dist-info → arbi-0.3.0.dist-info}/RECORD +44 -42
  43. arbi/resources/api/sso.py +0 -333
  44. arbi/types/api/sso_login_response.py +0 -15
  45. arbi/types/api/token.py +0 -13
  46. {arbi-0.2.0.dist-info → arbi-0.3.0.dist-info}/WHEEL +0 -0
  47. {arbi-0.2.0.dist-info → arbi-0.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,6 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from typing import Dict, Optional
6
+
5
7
  import httpx
6
8
 
7
9
  from .settings import (
@@ -12,7 +14,7 @@ from .settings import (
12
14
  SettingsResourceWithStreamingResponse,
13
15
  AsyncSettingsResourceWithStreamingResponse,
14
16
  )
15
- from ...._types import Body, Query, Headers, NotGiven, not_given
17
+ from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
16
18
  from ...._utils import maybe_transform, async_maybe_transform
17
19
  from ...._compat import cached_property
18
20
  from ...._resource import SyncAPIResource, AsyncAPIResource
@@ -22,13 +24,22 @@ from ...._response import (
22
24
  async_to_raw_response_wrapper,
23
25
  async_to_streamed_response_wrapper,
24
26
  )
25
- from ....types.api import user_login_params, user_register_params, user_verify_email_params
27
+ from ....types.api import (
28
+ user_login_params,
29
+ user_invite_params,
30
+ user_register_params,
31
+ user_verify_email_params,
32
+ user_change_password_params,
33
+ user_check_sso_status_params,
34
+ )
26
35
  from ...._base_client import make_request_options
27
- from ....types.api.token import Token
28
- from ....types.api.user_response import UserResponse
36
+ from ....types.api.user_login_response import UserLoginResponse
37
+ from ....types.api.user_invite_response import UserInviteResponse
29
38
  from ....types.api.user_logout_response import UserLogoutResponse
30
39
  from ....types.api.user_verify_email_response import UserVerifyEmailResponse
40
+ from ....types.api.user_change_password_response import UserChangePasswordResponse
31
41
  from ....types.api.user_list_workspaces_response import UserListWorkspacesResponse
42
+ from ....types.api.user_check_sso_status_response import UserCheckSSOStatusResponse
32
43
 
33
44
  __all__ = ["UserResource", "AsyncUserResource"]
34
45
 
@@ -57,42 +68,90 @@ class UserResource(SyncAPIResource):
57
68
  """
58
69
  return UserResourceWithStreamingResponse(self)
59
70
 
60
- def list_workspaces(
71
+ def change_password(
61
72
  self,
62
73
  *,
74
+ current_public_key: str,
75
+ new_public_key: str,
76
+ rewrapped_workspace_keys: Dict[str, str],
63
77
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
64
78
  # The extra values given here take precedence over values defined on the client or passed to this method.
65
79
  extra_headers: Headers | None = None,
66
80
  extra_query: Query | None = None,
67
81
  extra_body: Body | None = None,
68
82
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
69
- ) -> UserListWorkspacesResponse:
70
- """
71
- Retrieve the list of workspaces associated with the current authenticated user.
72
- Leverages RLS to enforce access control.
83
+ ) -> UserChangePasswordResponse:
84
+ """Change user's master password by re-keying all workspace keys.
85
+
86
+ Client must:
87
+
88
+ 1.
89
+
90
+ Prove knowledge of current master password via X25519 public key
91
+ 2. Provide new X25519 public key (derived from new master password)
92
+ 3. Re-wrap all workspace keys with new X25519 public key
93
+
94
+ Server will:
95
+
96
+ 1. Verify current master password (public key comparison)
97
+ 2. Update X25519 public key
98
+ 3. Update all workspace wrapped keys
99
+
100
+ Note: This changes the master password (encryption password), not authentication
101
+ password. Both local and SSO users can change their master password.
102
+
103
+ Args:
104
+ extra_headers: Send extra headers
105
+
106
+ extra_query: Add additional query parameters to the request
107
+
108
+ extra_body: Add additional JSON properties to the request
109
+
110
+ timeout: Override the client-level default timeout for this request, in seconds
73
111
  """
74
- return self._get(
75
- "/api/user/workspaces",
112
+ return self._post(
113
+ "/api/user/change_password",
114
+ body=maybe_transform(
115
+ {
116
+ "current_public_key": current_public_key,
117
+ "new_public_key": new_public_key,
118
+ "rewrapped_workspace_keys": rewrapped_workspace_keys,
119
+ },
120
+ user_change_password_params.UserChangePasswordParams,
121
+ ),
76
122
  options=make_request_options(
77
123
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
78
124
  ),
79
- cast_to=UserListWorkspacesResponse,
125
+ cast_to=UserChangePasswordResponse,
80
126
  )
81
127
 
82
- def login(
128
+ def check_sso_status(
83
129
  self,
84
130
  *,
85
131
  email: str,
86
- password: str,
132
+ sso_token: str,
87
133
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
88
134
  # The extra values given here take precedence over values defined on the client or passed to this method.
89
135
  extra_headers: Headers | None = None,
90
136
  extra_query: Query | None = None,
91
137
  extra_body: Body | None = None,
92
138
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
93
- ) -> Token:
94
- """
95
- Login a user and return a JWT token.
139
+ ) -> UserCheckSSOStatusResponse:
140
+ """Check SSO user registration state.
141
+
142
+ Returns one of three states:
143
+
144
+ 1.
145
+
146
+ new_user: No user exists with this email
147
+ 2. local_exists: User exists but registered locally (can link to SSO)
148
+ 3. sso_exists: User exists and already linked to SSO
149
+
150
+ Frontend uses this to show appropriate UI:
151
+
152
+ - new_user -> "Set Master Password"
153
+ - local_exists -> "Link SSO? Enter current master password"
154
+ - sso_exists -> "Enter Master Password"
96
155
 
97
156
  Args:
98
157
  extra_headers: Send extra headers
@@ -104,40 +163,59 @@ class UserResource(SyncAPIResource):
104
163
  timeout: Override the client-level default timeout for this request, in seconds
105
164
  """
106
165
  return self._post(
107
- "/api/user/login",
166
+ "/api/user/sso-status",
108
167
  body=maybe_transform(
109
168
  {
110
169
  "email": email,
111
- "password": password,
170
+ "sso_token": sso_token,
112
171
  },
113
- user_login_params.UserLoginParams,
172
+ user_check_sso_status_params.UserCheckSSOStatusParams,
114
173
  ),
115
174
  options=make_request_options(
116
175
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
117
176
  ),
118
- cast_to=Token,
177
+ cast_to=UserCheckSSOStatusResponse,
119
178
  )
120
179
 
121
- def logout(
180
+ def invite(
122
181
  self,
123
182
  *,
183
+ email: str,
124
184
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
125
185
  # The extra values given here take precedence over values defined on the client or passed to this method.
126
186
  extra_headers: Headers | None = None,
127
187
  extra_query: Query | None = None,
128
188
  extra_body: Body | None = None,
129
189
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
130
- ) -> UserLogoutResponse:
131
- """Log out the current user by clearing cached keys and refresh token cookie."""
190
+ ) -> UserInviteResponse:
191
+ """Send invitation email with 3-word verification code to a new user.
192
+
193
+ Protected
194
+ endpoint - requires authentication. Includes inviter's name in the email for
195
+ personalization.
196
+
197
+ Note: Fails silently if email already exists to prevent email enumeration
198
+ attacks.
199
+
200
+ Args:
201
+ extra_headers: Send extra headers
202
+
203
+ extra_query: Add additional query parameters to the request
204
+
205
+ extra_body: Add additional JSON properties to the request
206
+
207
+ timeout: Override the client-level default timeout for this request, in seconds
208
+ """
132
209
  return self._post(
133
- "/api/user/logout",
210
+ "/api/user/invite",
211
+ body=maybe_transform({"email": email}, user_invite_params.UserInviteParams),
134
212
  options=make_request_options(
135
213
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
136
214
  ),
137
- cast_to=UserLogoutResponse,
215
+ cast_to=UserInviteResponse,
138
216
  )
139
217
 
140
- def refresh_token(
218
+ def list_workspaces(
141
219
  self,
142
220
  *,
143
221
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -146,37 +224,44 @@ class UserResource(SyncAPIResource):
146
224
  extra_query: Query | None = None,
147
225
  extra_body: Body | None = None,
148
226
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
149
- ) -> Token:
150
- """Refresh an expired access token using the refresh token cookie.
151
-
152
- Validates the
153
- refresh token and issues a new access token.
227
+ ) -> UserListWorkspacesResponse:
154
228
  """
155
- return self._post(
156
- "/api/user/token_refresh",
229
+ Retrieve the list of workspaces associated with the current authenticated user.
230
+ Includes wrapped_key, stats (conversation/document counts with shared/private
231
+ breakdown), and users for each workspace. All data is fetched efficiently using
232
+ batch queries to avoid N+1 problems. Leverages RLS to enforce access control.
233
+ """
234
+ return self._get(
235
+ "/api/user/workspaces",
157
236
  options=make_request_options(
158
237
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
159
238
  ),
160
- cast_to=Token,
239
+ cast_to=UserListWorkspacesResponse,
161
240
  )
162
241
 
163
- def register(
242
+ def login(
164
243
  self,
165
244
  *,
166
245
  email: str,
167
- last_name: str,
168
- name: str,
169
- password: str,
170
- verification_code: str,
246
+ public_key: str,
247
+ sso_token: Optional[str] | Omit = omit,
171
248
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
172
249
  # The extra values given here take precedence over values defined on the client or passed to this method.
173
250
  extra_headers: Headers | None = None,
174
251
  extra_query: Query | None = None,
175
252
  extra_body: Body | None = None,
176
253
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
177
- ) -> UserResponse:
254
+ ) -> UserLoginResponse:
178
255
  """
179
- Register a new user with email verification.
256
+ Login with X25519 public key verification (local or SSO).
257
+
258
+ SIMPLEST POSSIBLE AUTH: Client derives X25519 public key from password and sends
259
+ it. Server compares with stored public key. Match = correct password!
260
+
261
+ For SSO users: Also validates SSO token before proceeding. For local users: Only
262
+ public key verification needed.
263
+
264
+ Returns encrypted login response that only the correct password can decrypt.
180
265
 
181
266
  Args:
182
267
  extra_headers: Send extra headers
@@ -188,24 +273,22 @@ class UserResource(SyncAPIResource):
188
273
  timeout: Override the client-level default timeout for this request, in seconds
189
274
  """
190
275
  return self._post(
191
- "/api/user/register",
276
+ "/api/user/login",
192
277
  body=maybe_transform(
193
278
  {
194
279
  "email": email,
195
- "last_name": last_name,
196
- "name": name,
197
- "password": password,
198
- "verification_code": verification_code,
280
+ "public_key": public_key,
281
+ "sso_token": sso_token,
199
282
  },
200
- user_register_params.UserRegisterParams,
283
+ user_login_params.UserLoginParams,
201
284
  ),
202
285
  options=make_request_options(
203
286
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
204
287
  ),
205
- cast_to=UserResponse,
288
+ cast_to=UserLoginResponse,
206
289
  )
207
290
 
208
- def retrieve_me(
291
+ def logout(
209
292
  self,
210
293
  *,
211
294
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -214,18 +297,66 @@ class UserResource(SyncAPIResource):
214
297
  extra_query: Query | None = None,
215
298
  extra_body: Body | None = None,
216
299
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
217
- ) -> UserResponse:
218
- """Retrieve current authenticated user information.
300
+ ) -> UserLogoutResponse:
301
+ """Log out the current user by clearing the refresh token cookie and session key."""
302
+ return self._post(
303
+ "/api/user/logout",
304
+ options=make_request_options(
305
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
306
+ ),
307
+ cast_to=UserLogoutResponse,
308
+ )
219
309
 
220
- This endpoint is useful for
221
- validating tokens and checking authentication status.
310
+ def register(
311
+ self,
312
+ *,
313
+ email: str,
314
+ public_key: str,
315
+ verification_credential: str,
316
+ last_name: Optional[str] | Omit = omit,
317
+ name: Optional[str] | Omit = omit,
318
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
319
+ # The extra values given here take precedence over values defined on the client or passed to this method.
320
+ extra_headers: Headers | None = None,
321
+ extra_query: Query | None = None,
322
+ extra_body: Body | None = None,
323
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
324
+ ) -> object:
222
325
  """
223
- return self._get(
224
- "/api/user/me",
326
+ Register a new user with email verification (local or SSO).
327
+
328
+ Accepts either:
329
+
330
+ - 3-word verification code for local users
331
+ - SSO JWT token for SSO users
332
+
333
+ Auto-detects credential type and handles both flows.
334
+
335
+ Args:
336
+ extra_headers: Send extra headers
337
+
338
+ extra_query: Add additional query parameters to the request
339
+
340
+ extra_body: Add additional JSON properties to the request
341
+
342
+ timeout: Override the client-level default timeout for this request, in seconds
343
+ """
344
+ return self._post(
345
+ "/api/user/register",
346
+ body=maybe_transform(
347
+ {
348
+ "email": email,
349
+ "public_key": public_key,
350
+ "verification_credential": verification_credential,
351
+ "last_name": last_name,
352
+ "name": name,
353
+ },
354
+ user_register_params.UserRegisterParams,
355
+ ),
225
356
  options=make_request_options(
226
357
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
227
358
  ),
228
- cast_to=UserResponse,
359
+ cast_to=object,
229
360
  )
230
361
 
231
362
  def verify_email(
@@ -290,42 +421,90 @@ class AsyncUserResource(AsyncAPIResource):
290
421
  """
291
422
  return AsyncUserResourceWithStreamingResponse(self)
292
423
 
293
- async def list_workspaces(
424
+ async def change_password(
294
425
  self,
295
426
  *,
427
+ current_public_key: str,
428
+ new_public_key: str,
429
+ rewrapped_workspace_keys: Dict[str, str],
296
430
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
297
431
  # The extra values given here take precedence over values defined on the client or passed to this method.
298
432
  extra_headers: Headers | None = None,
299
433
  extra_query: Query | None = None,
300
434
  extra_body: Body | None = None,
301
435
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
302
- ) -> UserListWorkspacesResponse:
303
- """
304
- Retrieve the list of workspaces associated with the current authenticated user.
305
- Leverages RLS to enforce access control.
436
+ ) -> UserChangePasswordResponse:
437
+ """Change user's master password by re-keying all workspace keys.
438
+
439
+ Client must:
440
+
441
+ 1.
442
+
443
+ Prove knowledge of current master password via X25519 public key
444
+ 2. Provide new X25519 public key (derived from new master password)
445
+ 3. Re-wrap all workspace keys with new X25519 public key
446
+
447
+ Server will:
448
+
449
+ 1. Verify current master password (public key comparison)
450
+ 2. Update X25519 public key
451
+ 3. Update all workspace wrapped keys
452
+
453
+ Note: This changes the master password (encryption password), not authentication
454
+ password. Both local and SSO users can change their master password.
455
+
456
+ Args:
457
+ extra_headers: Send extra headers
458
+
459
+ extra_query: Add additional query parameters to the request
460
+
461
+ extra_body: Add additional JSON properties to the request
462
+
463
+ timeout: Override the client-level default timeout for this request, in seconds
306
464
  """
307
- return await self._get(
308
- "/api/user/workspaces",
465
+ return await self._post(
466
+ "/api/user/change_password",
467
+ body=await async_maybe_transform(
468
+ {
469
+ "current_public_key": current_public_key,
470
+ "new_public_key": new_public_key,
471
+ "rewrapped_workspace_keys": rewrapped_workspace_keys,
472
+ },
473
+ user_change_password_params.UserChangePasswordParams,
474
+ ),
309
475
  options=make_request_options(
310
476
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
311
477
  ),
312
- cast_to=UserListWorkspacesResponse,
478
+ cast_to=UserChangePasswordResponse,
313
479
  )
314
480
 
315
- async def login(
481
+ async def check_sso_status(
316
482
  self,
317
483
  *,
318
484
  email: str,
319
- password: str,
485
+ sso_token: str,
320
486
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
321
487
  # The extra values given here take precedence over values defined on the client or passed to this method.
322
488
  extra_headers: Headers | None = None,
323
489
  extra_query: Query | None = None,
324
490
  extra_body: Body | None = None,
325
491
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
326
- ) -> Token:
327
- """
328
- Login a user and return a JWT token.
492
+ ) -> UserCheckSSOStatusResponse:
493
+ """Check SSO user registration state.
494
+
495
+ Returns one of three states:
496
+
497
+ 1.
498
+
499
+ new_user: No user exists with this email
500
+ 2. local_exists: User exists but registered locally (can link to SSO)
501
+ 3. sso_exists: User exists and already linked to SSO
502
+
503
+ Frontend uses this to show appropriate UI:
504
+
505
+ - new_user -> "Set Master Password"
506
+ - local_exists -> "Link SSO? Enter current master password"
507
+ - sso_exists -> "Enter Master Password"
329
508
 
330
509
  Args:
331
510
  extra_headers: Send extra headers
@@ -337,40 +516,59 @@ class AsyncUserResource(AsyncAPIResource):
337
516
  timeout: Override the client-level default timeout for this request, in seconds
338
517
  """
339
518
  return await self._post(
340
- "/api/user/login",
519
+ "/api/user/sso-status",
341
520
  body=await async_maybe_transform(
342
521
  {
343
522
  "email": email,
344
- "password": password,
523
+ "sso_token": sso_token,
345
524
  },
346
- user_login_params.UserLoginParams,
525
+ user_check_sso_status_params.UserCheckSSOStatusParams,
347
526
  ),
348
527
  options=make_request_options(
349
528
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
350
529
  ),
351
- cast_to=Token,
530
+ cast_to=UserCheckSSOStatusResponse,
352
531
  )
353
532
 
354
- async def logout(
533
+ async def invite(
355
534
  self,
356
535
  *,
536
+ email: str,
357
537
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
358
538
  # The extra values given here take precedence over values defined on the client or passed to this method.
359
539
  extra_headers: Headers | None = None,
360
540
  extra_query: Query | None = None,
361
541
  extra_body: Body | None = None,
362
542
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
363
- ) -> UserLogoutResponse:
364
- """Log out the current user by clearing cached keys and refresh token cookie."""
543
+ ) -> UserInviteResponse:
544
+ """Send invitation email with 3-word verification code to a new user.
545
+
546
+ Protected
547
+ endpoint - requires authentication. Includes inviter's name in the email for
548
+ personalization.
549
+
550
+ Note: Fails silently if email already exists to prevent email enumeration
551
+ attacks.
552
+
553
+ Args:
554
+ extra_headers: Send extra headers
555
+
556
+ extra_query: Add additional query parameters to the request
557
+
558
+ extra_body: Add additional JSON properties to the request
559
+
560
+ timeout: Override the client-level default timeout for this request, in seconds
561
+ """
365
562
  return await self._post(
366
- "/api/user/logout",
563
+ "/api/user/invite",
564
+ body=await async_maybe_transform({"email": email}, user_invite_params.UserInviteParams),
367
565
  options=make_request_options(
368
566
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
369
567
  ),
370
- cast_to=UserLogoutResponse,
568
+ cast_to=UserInviteResponse,
371
569
  )
372
570
 
373
- async def refresh_token(
571
+ async def list_workspaces(
374
572
  self,
375
573
  *,
376
574
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -379,37 +577,44 @@ class AsyncUserResource(AsyncAPIResource):
379
577
  extra_query: Query | None = None,
380
578
  extra_body: Body | None = None,
381
579
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
382
- ) -> Token:
383
- """Refresh an expired access token using the refresh token cookie.
384
-
385
- Validates the
386
- refresh token and issues a new access token.
580
+ ) -> UserListWorkspacesResponse:
387
581
  """
388
- return await self._post(
389
- "/api/user/token_refresh",
582
+ Retrieve the list of workspaces associated with the current authenticated user.
583
+ Includes wrapped_key, stats (conversation/document counts with shared/private
584
+ breakdown), and users for each workspace. All data is fetched efficiently using
585
+ batch queries to avoid N+1 problems. Leverages RLS to enforce access control.
586
+ """
587
+ return await self._get(
588
+ "/api/user/workspaces",
390
589
  options=make_request_options(
391
590
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
392
591
  ),
393
- cast_to=Token,
592
+ cast_to=UserListWorkspacesResponse,
394
593
  )
395
594
 
396
- async def register(
595
+ async def login(
397
596
  self,
398
597
  *,
399
598
  email: str,
400
- last_name: str,
401
- name: str,
402
- password: str,
403
- verification_code: str,
599
+ public_key: str,
600
+ sso_token: Optional[str] | Omit = omit,
404
601
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
405
602
  # The extra values given here take precedence over values defined on the client or passed to this method.
406
603
  extra_headers: Headers | None = None,
407
604
  extra_query: Query | None = None,
408
605
  extra_body: Body | None = None,
409
606
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
410
- ) -> UserResponse:
607
+ ) -> UserLoginResponse:
411
608
  """
412
- Register a new user with email verification.
609
+ Login with X25519 public key verification (local or SSO).
610
+
611
+ SIMPLEST POSSIBLE AUTH: Client derives X25519 public key from password and sends
612
+ it. Server compares with stored public key. Match = correct password!
613
+
614
+ For SSO users: Also validates SSO token before proceeding. For local users: Only
615
+ public key verification needed.
616
+
617
+ Returns encrypted login response that only the correct password can decrypt.
413
618
 
414
619
  Args:
415
620
  extra_headers: Send extra headers
@@ -421,24 +626,22 @@ class AsyncUserResource(AsyncAPIResource):
421
626
  timeout: Override the client-level default timeout for this request, in seconds
422
627
  """
423
628
  return await self._post(
424
- "/api/user/register",
629
+ "/api/user/login",
425
630
  body=await async_maybe_transform(
426
631
  {
427
632
  "email": email,
428
- "last_name": last_name,
429
- "name": name,
430
- "password": password,
431
- "verification_code": verification_code,
633
+ "public_key": public_key,
634
+ "sso_token": sso_token,
432
635
  },
433
- user_register_params.UserRegisterParams,
636
+ user_login_params.UserLoginParams,
434
637
  ),
435
638
  options=make_request_options(
436
639
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
437
640
  ),
438
- cast_to=UserResponse,
641
+ cast_to=UserLoginResponse,
439
642
  )
440
643
 
441
- async def retrieve_me(
644
+ async def logout(
442
645
  self,
443
646
  *,
444
647
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -447,18 +650,66 @@ class AsyncUserResource(AsyncAPIResource):
447
650
  extra_query: Query | None = None,
448
651
  extra_body: Body | None = None,
449
652
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
450
- ) -> UserResponse:
451
- """Retrieve current authenticated user information.
653
+ ) -> UserLogoutResponse:
654
+ """Log out the current user by clearing the refresh token cookie and session key."""
655
+ return await self._post(
656
+ "/api/user/logout",
657
+ options=make_request_options(
658
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
659
+ ),
660
+ cast_to=UserLogoutResponse,
661
+ )
452
662
 
453
- This endpoint is useful for
454
- validating tokens and checking authentication status.
663
+ async def register(
664
+ self,
665
+ *,
666
+ email: str,
667
+ public_key: str,
668
+ verification_credential: str,
669
+ last_name: Optional[str] | Omit = omit,
670
+ name: Optional[str] | Omit = omit,
671
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
672
+ # The extra values given here take precedence over values defined on the client or passed to this method.
673
+ extra_headers: Headers | None = None,
674
+ extra_query: Query | None = None,
675
+ extra_body: Body | None = None,
676
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
677
+ ) -> object:
455
678
  """
456
- return await self._get(
457
- "/api/user/me",
679
+ Register a new user with email verification (local or SSO).
680
+
681
+ Accepts either:
682
+
683
+ - 3-word verification code for local users
684
+ - SSO JWT token for SSO users
685
+
686
+ Auto-detects credential type and handles both flows.
687
+
688
+ Args:
689
+ extra_headers: Send extra headers
690
+
691
+ extra_query: Add additional query parameters to the request
692
+
693
+ extra_body: Add additional JSON properties to the request
694
+
695
+ timeout: Override the client-level default timeout for this request, in seconds
696
+ """
697
+ return await self._post(
698
+ "/api/user/register",
699
+ body=await async_maybe_transform(
700
+ {
701
+ "email": email,
702
+ "public_key": public_key,
703
+ "verification_credential": verification_credential,
704
+ "last_name": last_name,
705
+ "name": name,
706
+ },
707
+ user_register_params.UserRegisterParams,
708
+ ),
458
709
  options=make_request_options(
459
710
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
460
711
  ),
461
- cast_to=UserResponse,
712
+ cast_to=object,
462
713
  )
463
714
 
464
715
  async def verify_email(
@@ -503,6 +754,15 @@ class UserResourceWithRawResponse:
503
754
  def __init__(self, user: UserResource) -> None:
504
755
  self._user = user
505
756
 
757
+ self.change_password = to_raw_response_wrapper(
758
+ user.change_password,
759
+ )
760
+ self.check_sso_status = to_raw_response_wrapper(
761
+ user.check_sso_status,
762
+ )
763
+ self.invite = to_raw_response_wrapper(
764
+ user.invite,
765
+ )
506
766
  self.list_workspaces = to_raw_response_wrapper(
507
767
  user.list_workspaces,
508
768
  )
@@ -512,15 +772,9 @@ class UserResourceWithRawResponse:
512
772
  self.logout = to_raw_response_wrapper(
513
773
  user.logout,
514
774
  )
515
- self.refresh_token = to_raw_response_wrapper(
516
- user.refresh_token,
517
- )
518
775
  self.register = to_raw_response_wrapper(
519
776
  user.register,
520
777
  )
521
- self.retrieve_me = to_raw_response_wrapper(
522
- user.retrieve_me,
523
- )
524
778
  self.verify_email = to_raw_response_wrapper(
525
779
  user.verify_email,
526
780
  )
@@ -534,6 +788,15 @@ class AsyncUserResourceWithRawResponse:
534
788
  def __init__(self, user: AsyncUserResource) -> None:
535
789
  self._user = user
536
790
 
791
+ self.change_password = async_to_raw_response_wrapper(
792
+ user.change_password,
793
+ )
794
+ self.check_sso_status = async_to_raw_response_wrapper(
795
+ user.check_sso_status,
796
+ )
797
+ self.invite = async_to_raw_response_wrapper(
798
+ user.invite,
799
+ )
537
800
  self.list_workspaces = async_to_raw_response_wrapper(
538
801
  user.list_workspaces,
539
802
  )
@@ -543,15 +806,9 @@ class AsyncUserResourceWithRawResponse:
543
806
  self.logout = async_to_raw_response_wrapper(
544
807
  user.logout,
545
808
  )
546
- self.refresh_token = async_to_raw_response_wrapper(
547
- user.refresh_token,
548
- )
549
809
  self.register = async_to_raw_response_wrapper(
550
810
  user.register,
551
811
  )
552
- self.retrieve_me = async_to_raw_response_wrapper(
553
- user.retrieve_me,
554
- )
555
812
  self.verify_email = async_to_raw_response_wrapper(
556
813
  user.verify_email,
557
814
  )
@@ -565,6 +822,15 @@ class UserResourceWithStreamingResponse:
565
822
  def __init__(self, user: UserResource) -> None:
566
823
  self._user = user
567
824
 
825
+ self.change_password = to_streamed_response_wrapper(
826
+ user.change_password,
827
+ )
828
+ self.check_sso_status = to_streamed_response_wrapper(
829
+ user.check_sso_status,
830
+ )
831
+ self.invite = to_streamed_response_wrapper(
832
+ user.invite,
833
+ )
568
834
  self.list_workspaces = to_streamed_response_wrapper(
569
835
  user.list_workspaces,
570
836
  )
@@ -574,15 +840,9 @@ class UserResourceWithStreamingResponse:
574
840
  self.logout = to_streamed_response_wrapper(
575
841
  user.logout,
576
842
  )
577
- self.refresh_token = to_streamed_response_wrapper(
578
- user.refresh_token,
579
- )
580
843
  self.register = to_streamed_response_wrapper(
581
844
  user.register,
582
845
  )
583
- self.retrieve_me = to_streamed_response_wrapper(
584
- user.retrieve_me,
585
- )
586
846
  self.verify_email = to_streamed_response_wrapper(
587
847
  user.verify_email,
588
848
  )
@@ -596,6 +856,15 @@ class AsyncUserResourceWithStreamingResponse:
596
856
  def __init__(self, user: AsyncUserResource) -> None:
597
857
  self._user = user
598
858
 
859
+ self.change_password = async_to_streamed_response_wrapper(
860
+ user.change_password,
861
+ )
862
+ self.check_sso_status = async_to_streamed_response_wrapper(
863
+ user.check_sso_status,
864
+ )
865
+ self.invite = async_to_streamed_response_wrapper(
866
+ user.invite,
867
+ )
599
868
  self.list_workspaces = async_to_streamed_response_wrapper(
600
869
  user.list_workspaces,
601
870
  )
@@ -605,15 +874,9 @@ class AsyncUserResourceWithStreamingResponse:
605
874
  self.logout = async_to_streamed_response_wrapper(
606
875
  user.logout,
607
876
  )
608
- self.refresh_token = async_to_streamed_response_wrapper(
609
- user.refresh_token,
610
- )
611
877
  self.register = async_to_streamed_response_wrapper(
612
878
  user.register,
613
879
  )
614
- self.retrieve_me = async_to_streamed_response_wrapper(
615
- user.retrieve_me,
616
- )
617
880
  self.verify_email = async_to_streamed_response_wrapper(
618
881
  user.verify_email,
619
882
  )