modulex-python 0.1.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 (47) hide show
  1. modulex/__init__.py +39 -0
  2. modulex/_base.py +281 -0
  3. modulex/_client.py +237 -0
  4. modulex/_compat.py +39 -0
  5. modulex/_config.py +26 -0
  6. modulex/_exceptions.py +131 -0
  7. modulex/_streaming.py +118 -0
  8. modulex/py.typed +0 -0
  9. modulex/resources/__init__.py +1 -0
  10. modulex/resources/api_keys.py +39 -0
  11. modulex/resources/auth.py +38 -0
  12. modulex/resources/chats.py +62 -0
  13. modulex/resources/composer.py +134 -0
  14. modulex/resources/credentials.py +197 -0
  15. modulex/resources/dashboard.py +110 -0
  16. modulex/resources/deployments.py +92 -0
  17. modulex/resources/executions.py +97 -0
  18. modulex/resources/integrations.py +110 -0
  19. modulex/resources/knowledge.py +343 -0
  20. modulex/resources/notifications.py +39 -0
  21. modulex/resources/organizations.py +72 -0
  22. modulex/resources/schedules.py +172 -0
  23. modulex/resources/subscriptions.py +38 -0
  24. modulex/resources/system.py +28 -0
  25. modulex/resources/templates.py +115 -0
  26. modulex/resources/workflows.py +156 -0
  27. modulex/types/__init__.py +294 -0
  28. modulex/types/api_keys.py +19 -0
  29. modulex/types/auth.py +62 -0
  30. modulex/types/chats.py +55 -0
  31. modulex/types/composer.py +27 -0
  32. modulex/types/credentials.py +79 -0
  33. modulex/types/dashboard.py +54 -0
  34. modulex/types/executions.py +104 -0
  35. modulex/types/integrations.py +29 -0
  36. modulex/types/knowledge.py +75 -0
  37. modulex/types/notifications.py +16 -0
  38. modulex/types/organizations.py +43 -0
  39. modulex/types/schedules.py +48 -0
  40. modulex/types/shared.py +39 -0
  41. modulex/types/subscriptions.py +59 -0
  42. modulex/types/templates.py +50 -0
  43. modulex/types/workflows.py +253 -0
  44. modulex_python-0.1.0.dist-info/METADATA +435 -0
  45. modulex_python-0.1.0.dist-info/RECORD +47 -0
  46. modulex_python-0.1.0.dist-info/WHEEL +4 -0
  47. modulex_python-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,115 @@
1
+ """Templates resource for the ModuleX Python SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import builtins
6
+ from typing import Any
7
+
8
+ from modulex._base import _BaseResource
9
+
10
+
11
+ class Templates(_BaseResource):
12
+ """Resource for browsing, creating, and managing workflow templates."""
13
+
14
+ async def list(self) -> Any:
15
+ """Return all publicly available templates."""
16
+ return await self._get("/templates")
17
+
18
+ async def get(self, template_id: str) -> Any:
19
+ """Return a single template by its ID."""
20
+ return await self._get(f"/templates/{template_id}")
21
+
22
+ async def my_templates(self) -> Any:
23
+ """Return all templates created by the authenticated user."""
24
+ return await self._get("/templates/me")
25
+
26
+ async def create(
27
+ self,
28
+ workflow_id: str,
29
+ name: str,
30
+ *,
31
+ description: str | None = None,
32
+ tags: builtins.list[str] | None = None,
33
+ schema_image_url: str | None = None,
34
+ organization_id: str | None = None,
35
+ ) -> Any:
36
+ """Create a new template from an existing workflow."""
37
+ body: dict[str, Any] = {
38
+ k: v
39
+ for k, v in {
40
+ "workflow_id": workflow_id,
41
+ "name": name,
42
+ "description": description,
43
+ "tags": tags,
44
+ "schema_image_url": schema_image_url,
45
+ }.items()
46
+ if v is not None
47
+ }
48
+ return await self._post("/templates", json=body, organization_id=organization_id)
49
+
50
+ async def like(self, template_id: str) -> Any:
51
+ """Toggle a like on a template for the authenticated user."""
52
+ return await self._post(f"/templates/{template_id}/like")
53
+
54
+ async def use(
55
+ self,
56
+ template_id: str,
57
+ *,
58
+ organization_id: str | None = None,
59
+ ) -> Any:
60
+ """Instantiate a workflow from a template into the caller's organization."""
61
+ return await self._post(f"/templates/{template_id}/use", organization_id=organization_id)
62
+
63
+ async def update_request(
64
+ self,
65
+ template_id: str,
66
+ workflow_id: str,
67
+ *,
68
+ name: str | None = None,
69
+ description: str | None = None,
70
+ tags: builtins.list[str] | None = None,
71
+ schema_image_url: str | None = None,
72
+ organization_id: str | None = None,
73
+ ) -> Any:
74
+ """Submit an update request to refresh a published template from a workflow."""
75
+ body: dict[str, Any] = {
76
+ k: v
77
+ for k, v in {
78
+ "workflow_id": workflow_id,
79
+ "name": name,
80
+ "description": description,
81
+ "tags": tags,
82
+ "schema_image_url": schema_image_url,
83
+ }.items()
84
+ if v is not None
85
+ }
86
+ return await self._post(
87
+ f"/templates/{template_id}/update-request",
88
+ json=body,
89
+ organization_id=organization_id,
90
+ )
91
+
92
+ async def create_creator(
93
+ self,
94
+ name: str,
95
+ *,
96
+ about: str | None = None,
97
+ display_photo: str | None = None,
98
+ socials: dict[str, Any] | None = None,
99
+ ) -> Any:
100
+ """Create a creator profile for the authenticated user."""
101
+ body: dict[str, Any] = {
102
+ k: v
103
+ for k, v in {
104
+ "name": name,
105
+ "about": about,
106
+ "display_photo": display_photo,
107
+ "socials": socials,
108
+ }.items()
109
+ if v is not None
110
+ }
111
+ return await self._post("/templates/creators", json=body)
112
+
113
+ async def my_creator(self) -> Any:
114
+ """Return the creator profile of the authenticated user."""
115
+ return await self._get("/templates/creators/me")
@@ -0,0 +1,156 @@
1
+ """Workflows resource for the ModuleX Python SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import AsyncIterator
6
+ from typing import Any
7
+
8
+ from modulex._base import _BaseResource
9
+ from modulex._streaming import EventSourceStream
10
+
11
+
12
+ class Workflows(_BaseResource):
13
+ """Resource for creating and managing workflow definitions."""
14
+
15
+ async def create(
16
+ self,
17
+ workflow_schema: dict[str, Any],
18
+ *,
19
+ name: str | None = None,
20
+ description: str | None = None,
21
+ version: str | None = None,
22
+ tags: list[str] | None = None,
23
+ category: str | None = None,
24
+ status: str = "draft",
25
+ visibility: str = "private",
26
+ input: dict[str, Any] | None = None,
27
+ config: dict[str, Any] | None = None,
28
+ organization_id: str | None = None,
29
+ ) -> Any:
30
+ """Create a new workflow from the given schema and metadata."""
31
+ body: dict[str, Any] = {
32
+ "workflow_schema": workflow_schema,
33
+ "status": status,
34
+ "visibility": visibility,
35
+ }
36
+ if name is not None:
37
+ body["name"] = name
38
+ if description is not None:
39
+ body["description"] = description
40
+ if version is not None:
41
+ body["version"] = version
42
+ if tags is not None:
43
+ body["tags"] = tags
44
+ if category is not None:
45
+ body["category"] = category
46
+ if input is not None:
47
+ body["input"] = input
48
+ if config is not None:
49
+ body["config"] = config
50
+ return await self._post("/workflows", json=body, organization_id=organization_id)
51
+
52
+ async def list(
53
+ self,
54
+ *,
55
+ status: str | None = None,
56
+ category: str | None = None,
57
+ visibility: str | None = None,
58
+ search: str | None = None,
59
+ page: int | None = None,
60
+ page_size: int | None = None,
61
+ organization_id: str | None = None,
62
+ ) -> Any:
63
+ """Return a paginated list of workflows matching the given filters."""
64
+ params: dict[str, Any] = {}
65
+ if status is not None:
66
+ params["status"] = status
67
+ if category is not None:
68
+ params["category"] = category
69
+ if visibility is not None:
70
+ params["visibility"] = visibility
71
+ if search is not None:
72
+ params["search"] = search
73
+ if page is not None:
74
+ params["page"] = page
75
+ if page_size is not None:
76
+ params["page_size"] = page_size
77
+ return await self._get("/workflows", params=params or None, organization_id=organization_id)
78
+
79
+ async def list_all(
80
+ self,
81
+ *,
82
+ status: str | None = None,
83
+ category: str | None = None,
84
+ visibility: str | None = None,
85
+ search: str | None = None,
86
+ organization_id: str | None = None,
87
+ ) -> AsyncIterator[Any]:
88
+ """Auto-paginate through all workflows matching the given filters."""
89
+ params: dict[str, Any] = {}
90
+ if status is not None:
91
+ params["status"] = status
92
+ if category is not None:
93
+ params["category"] = category
94
+ if visibility is not None:
95
+ params["visibility"] = visibility
96
+ if search is not None:
97
+ params["search"] = search
98
+ params["page"] = 1
99
+ async for item in self._paginate(
100
+ "/workflows",
101
+ items_key="workflows",
102
+ params=params,
103
+ organization_id=organization_id,
104
+ ):
105
+ yield item
106
+
107
+ async def get(self, workflow_id: str, *, organization_id: str | None = None) -> Any:
108
+ """Return a single workflow by its ID."""
109
+ return await self._get(f"/workflows/{workflow_id}", organization_id=organization_id)
110
+
111
+ async def update(self, workflow_id: str, *, organization_id: str | None = None, **kwargs: Any) -> Any:
112
+ """Update a workflow's fields with any combination of allowed keys."""
113
+ allowed_keys = {
114
+ "name",
115
+ "description",
116
+ "version",
117
+ "tags",
118
+ "category",
119
+ "status",
120
+ "visibility",
121
+ "workflow_schema",
122
+ "input",
123
+ "config",
124
+ }
125
+ body = {k: v for k, v in kwargs.items() if k in allowed_keys and v is not None}
126
+ return await self._put(f"/workflows/{workflow_id}", json=body, organization_id=organization_id)
127
+
128
+ async def delete(self, workflow_id: str, *, organization_id: str | None = None) -> Any:
129
+ """Delete a workflow by its ID."""
130
+ return await self._delete(f"/workflows/{workflow_id}", organization_id=organization_id)
131
+
132
+ async def builder_details(
133
+ self,
134
+ *,
135
+ node_type: str | None = None,
136
+ category: str | None = None,
137
+ integration_name: str | None = None,
138
+ organization_id: str | None = None,
139
+ ) -> Any:
140
+ """Return workflow builder node details, optionally filtered by type, category, or integration."""
141
+ params: dict[str, Any] = {}
142
+ if node_type is not None:
143
+ params["node_type"] = node_type
144
+ if category is not None:
145
+ params["category"] = category
146
+ if integration_name is not None:
147
+ params["integration_name"] = integration_name
148
+ return await self._get(
149
+ "/workflows/builder/details",
150
+ params=params or None,
151
+ organization_id=organization_id,
152
+ )
153
+
154
+ def listen_changes(self, workflow_id: str, *, organization_id: str | None = None) -> EventSourceStream:
155
+ """Open an SSE stream for live changes to a workflow definition."""
156
+ return self._stream_sse(f"/workflows/{workflow_id}/changes", organization_id=organization_id)
@@ -0,0 +1,294 @@
1
+ """ModuleX SDK type definitions.
2
+
3
+ Re-exports every public type from all submodules so callers can use a single
4
+ import path:
5
+
6
+ from modulex.types import WorkflowResponse, CredentialResponse, ...
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ # ---------------------------------------------------------------------------
12
+ # api_keys
13
+ # ---------------------------------------------------------------------------
14
+ from modulex.types.api_keys import (
15
+ ApiKeyResponse,
16
+ )
17
+
18
+ # ---------------------------------------------------------------------------
19
+ # auth
20
+ # ---------------------------------------------------------------------------
21
+ from modulex.types.auth import (
22
+ InvitationInfo,
23
+ LeaveOrganizationResponse,
24
+ OrganizationMembership,
25
+ UserOrganizationsResponse,
26
+ UserProfile,
27
+ )
28
+
29
+ # ---------------------------------------------------------------------------
30
+ # chats
31
+ # ---------------------------------------------------------------------------
32
+ from modulex.types.chats import (
33
+ ChatListResponse,
34
+ ChatMessageResponse,
35
+ ChatMessagesListResponse,
36
+ ChatResponse,
37
+ )
38
+
39
+ # ---------------------------------------------------------------------------
40
+ # composer
41
+ # ---------------------------------------------------------------------------
42
+ from modulex.types.composer import (
43
+ ComposerChatResponse,
44
+ ComposerStatusResponse,
45
+ )
46
+
47
+ # ---------------------------------------------------------------------------
48
+ # credentials
49
+ # ---------------------------------------------------------------------------
50
+ from modulex.types.credentials import (
51
+ AuditEntry,
52
+ CredentialResponse,
53
+ CredentialTestResult,
54
+ CredentialUsageStats,
55
+ MCPRefreshResponse,
56
+ MCPToolsResponse,
57
+ )
58
+
59
+ # ---------------------------------------------------------------------------
60
+ # dashboard
61
+ # ---------------------------------------------------------------------------
62
+ from modulex.types.dashboard import (
63
+ AnalyticsOverviewResponse,
64
+ LogEntry,
65
+ LogsResponse,
66
+ UserListResponse,
67
+ )
68
+
69
+ # ---------------------------------------------------------------------------
70
+ # executions
71
+ # ---------------------------------------------------------------------------
72
+ from modulex.types.executions import (
73
+ CancelResponse,
74
+ DoneEvent,
75
+ ErrorEvent,
76
+ InterruptEvent,
77
+ MetadataEvent,
78
+ NodeUpdateEvent,
79
+ ResumeResponse,
80
+ RunResponse,
81
+ StateResponse,
82
+ )
83
+
84
+ # ---------------------------------------------------------------------------
85
+ # integrations
86
+ # ---------------------------------------------------------------------------
87
+ from modulex.types.integrations import (
88
+ IntegrationBrowseResponse,
89
+ IntegrationInfo,
90
+ )
91
+
92
+ # ---------------------------------------------------------------------------
93
+ # knowledge
94
+ # ---------------------------------------------------------------------------
95
+ from modulex.types.knowledge import (
96
+ ChunkInfo,
97
+ ContextResponse,
98
+ DocumentResponse,
99
+ KnowledgeBaseResponse,
100
+ KnowledgeStatsResponse,
101
+ SearchResult,
102
+ SupportedFileTypesResponse,
103
+ )
104
+
105
+ # ---------------------------------------------------------------------------
106
+ # notifications
107
+ # ---------------------------------------------------------------------------
108
+ from modulex.types.notifications import (
109
+ NotificationResponse,
110
+ )
111
+
112
+ # ---------------------------------------------------------------------------
113
+ # organizations
114
+ # ---------------------------------------------------------------------------
115
+ from modulex.types.organizations import (
116
+ InviteResponse,
117
+ LLMListResponse,
118
+ OrganizationResponse,
119
+ RoleUpdateResponse,
120
+ )
121
+
122
+ # ---------------------------------------------------------------------------
123
+ # schedules
124
+ # ---------------------------------------------------------------------------
125
+ from modulex.types.schedules import (
126
+ RunStatsResponse,
127
+ ScheduleResponse,
128
+ ScheduleRunResponse,
129
+ )
130
+
131
+ # ---------------------------------------------------------------------------
132
+ # shared
133
+ # ---------------------------------------------------------------------------
134
+ from modulex.types.shared import (
135
+ ErrorDetail,
136
+ PagePaginatedResponse,
137
+ PaginatedResponse,
138
+ SuccessResponse,
139
+ )
140
+
141
+ # ---------------------------------------------------------------------------
142
+ # subscriptions
143
+ # ---------------------------------------------------------------------------
144
+ from modulex.types.subscriptions import (
145
+ BillingResponse,
146
+ BillingSubscription,
147
+ CheckoutResponse,
148
+ PlanInfo,
149
+ PlanPrice,
150
+ PlansResponse,
151
+ )
152
+
153
+ # ---------------------------------------------------------------------------
154
+ # templates
155
+ # ---------------------------------------------------------------------------
156
+ from modulex.types.templates import (
157
+ CreatorProfile,
158
+ TemplateListResponse,
159
+ TemplateResponse,
160
+ )
161
+
162
+ # ---------------------------------------------------------------------------
163
+ # workflows
164
+ # ---------------------------------------------------------------------------
165
+ from modulex.types.workflows import (
166
+ AgentNodeConfig,
167
+ BuilderDetailsResponse,
168
+ ConditionalNodeConfig,
169
+ EdgeDefinition,
170
+ ExpressionBranch,
171
+ GuardrailsNodeConfig,
172
+ InterruptNodeConfig,
173
+ KnowledgeNodeConfig,
174
+ LLMConfig,
175
+ LLMNodeConfig,
176
+ LoopConfig,
177
+ NodeDefinition,
178
+ RetryConfig,
179
+ StateField,
180
+ StateSchema,
181
+ ToolDefinition,
182
+ ToolNodeConfig,
183
+ TransformerNodeConfig,
184
+ TransformerOperation,
185
+ WorkflowConfig,
186
+ WorkflowDefinition,
187
+ WorkflowListResponse,
188
+ WorkflowMetadata,
189
+ WorkflowResponse,
190
+ )
191
+
192
+ __all__ = [
193
+ # api_keys
194
+ "ApiKeyResponse",
195
+ # auth
196
+ "InvitationInfo",
197
+ "LeaveOrganizationResponse",
198
+ "OrganizationMembership",
199
+ "UserOrganizationsResponse",
200
+ "UserProfile",
201
+ # chats
202
+ "ChatListResponse",
203
+ "ChatMessageResponse",
204
+ "ChatMessagesListResponse",
205
+ "ChatResponse",
206
+ # composer
207
+ "ComposerChatResponse",
208
+ "ComposerStatusResponse",
209
+ # credentials
210
+ "AuditEntry",
211
+ "CredentialResponse",
212
+ "CredentialTestResult",
213
+ "CredentialUsageStats",
214
+ "MCPRefreshResponse",
215
+ "MCPToolsResponse",
216
+ # dashboard
217
+ "AnalyticsOverviewResponse",
218
+ "LogEntry",
219
+ "LogsResponse",
220
+ "UserListResponse",
221
+ # executions
222
+ "CancelResponse",
223
+ "DoneEvent",
224
+ "ErrorEvent",
225
+ "InterruptEvent",
226
+ "MetadataEvent",
227
+ "NodeUpdateEvent",
228
+ "ResumeResponse",
229
+ "RunResponse",
230
+ "StateResponse",
231
+ # integrations
232
+ "IntegrationBrowseResponse",
233
+ "IntegrationInfo",
234
+ # knowledge
235
+ "ChunkInfo",
236
+ "ContextResponse",
237
+ "DocumentResponse",
238
+ "KnowledgeBaseResponse",
239
+ "KnowledgeStatsResponse",
240
+ "SearchResult",
241
+ "SupportedFileTypesResponse",
242
+ # notifications
243
+ "NotificationResponse",
244
+ # organizations
245
+ "InviteResponse",
246
+ "LLMListResponse",
247
+ "OrganizationResponse",
248
+ "RoleUpdateResponse",
249
+ # schedules
250
+ "RunStatsResponse",
251
+ "ScheduleResponse",
252
+ "ScheduleRunResponse",
253
+ # shared
254
+ "ErrorDetail",
255
+ "PagePaginatedResponse",
256
+ "PaginatedResponse",
257
+ "SuccessResponse",
258
+ # subscriptions
259
+ "BillingResponse",
260
+ "BillingSubscription",
261
+ "CheckoutResponse",
262
+ "PlanInfo",
263
+ "PlanPrice",
264
+ "PlansResponse",
265
+ # templates
266
+ "CreatorProfile",
267
+ "TemplateListResponse",
268
+ "TemplateResponse",
269
+ # workflows
270
+ "AgentNodeConfig",
271
+ "BuilderDetailsResponse",
272
+ "ConditionalNodeConfig",
273
+ "EdgeDefinition",
274
+ "ExpressionBranch",
275
+ "GuardrailsNodeConfig",
276
+ "InterruptNodeConfig",
277
+ "KnowledgeNodeConfig",
278
+ "LLMConfig",
279
+ "LLMNodeConfig",
280
+ "LoopConfig",
281
+ "NodeDefinition",
282
+ "RetryConfig",
283
+ "StateField",
284
+ "StateSchema",
285
+ "ToolDefinition",
286
+ "ToolNodeConfig",
287
+ "TransformerNodeConfig",
288
+ "TransformerOperation",
289
+ "WorkflowConfig",
290
+ "WorkflowDefinition",
291
+ "WorkflowListResponse",
292
+ "WorkflowMetadata",
293
+ "WorkflowResponse",
294
+ ]
@@ -0,0 +1,19 @@
1
+ """API key-related type definitions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing_extensions import TypedDict
6
+
7
+
8
+ class ApiKeyResponse(TypedDict, total=False):
9
+ """Response representing an API key."""
10
+
11
+ id: str
12
+ name: str
13
+ key: str | None
14
+ key_hint: str
15
+ organization_id: str
16
+ expires_at: str | None
17
+ rate_limit_per_minute: int | None
18
+ created_at: str
19
+ is_revoked: bool
modulex/types/auth.py ADDED
@@ -0,0 +1,62 @@
1
+ """Auth-related type definitions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from typing_extensions import TypedDict
8
+
9
+
10
+ class UserProfile(TypedDict, total=False):
11
+ """User profile from /auth/me."""
12
+
13
+ id: str
14
+ email: str
15
+ username: str
16
+ role: str
17
+ is_active: bool
18
+ organization_ids: list[str]
19
+ primary_organization_id: str | None
20
+
21
+
22
+ class OrganizationMembership(TypedDict, total=False):
23
+ """Organization membership info."""
24
+
25
+ id: str
26
+ name: str
27
+ slug: str
28
+ role: str
29
+ created_at: str
30
+
31
+
32
+ class UserOrganizationsResponse(TypedDict, total=False):
33
+ """Response from /auth/me/organizations."""
34
+
35
+ success: bool
36
+ user_id: str
37
+ organizations: list[OrganizationMembership]
38
+ total: int
39
+
40
+
41
+ class InvitationInfo(TypedDict, total=False):
42
+ """Invitation details."""
43
+
44
+ id: str
45
+ organization_id: str
46
+ organization_name: str
47
+ invited_email: str
48
+ role: str
49
+ status: str
50
+ invitation_message: str | None
51
+ created_at: str
52
+ expires_at: str | None
53
+
54
+
55
+ class LeaveOrganizationResponse(TypedDict, total=False):
56
+ """Response from /auth/organizations/leave."""
57
+
58
+ success: bool
59
+ message: str
60
+ left_organization: dict[str, Any]
61
+ remaining_organizations: list[dict[str, Any]]
62
+ total_remaining: int
modulex/types/chats.py ADDED
@@ -0,0 +1,55 @@
1
+ """Chat-related type definitions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from typing_extensions import TypedDict
8
+
9
+
10
+ class ChatResponse(TypedDict, total=False):
11
+ """Response representing a chat session."""
12
+
13
+ id: str
14
+ organization_id: str
15
+ creator_id: str
16
+ title: str | None
17
+ is_private: bool
18
+ running_id: str | None
19
+ messages: list[Any]
20
+ created_at: str
21
+ updated_at: str
22
+ deleted_at: str | None
23
+
24
+
25
+ class ChatMessageResponse(TypedDict, total=False):
26
+ """Response representing a single chat message."""
27
+
28
+ id: str
29
+ chat_id: str
30
+ role: str
31
+ content: Any
32
+ workflow: dict[str, Any]
33
+ run_id: str | None
34
+ running_status: str | None
35
+ created_at: str
36
+ updated_at: str
37
+
38
+
39
+ class ChatListResponse(TypedDict, total=False):
40
+ """Categorized list of chats for the current user."""
41
+
42
+ chats: list[Any]
43
+ pinned: list[Any]
44
+ archived: list[Any]
45
+
46
+
47
+ class ChatMessagesListResponse(TypedDict, total=False):
48
+ """Paginated list of messages within a chat."""
49
+
50
+ messages: list[Any]
51
+ total: int
52
+ limit: int
53
+ offset: int
54
+ has_next: bool
55
+ actual_count: int