magickmind 0.1.1__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 (43) hide show
  1. magick_mind/__init__.py +39 -0
  2. magick_mind/auth/__init__.py +9 -0
  3. magick_mind/auth/base.py +46 -0
  4. magick_mind/auth/email_password.py +268 -0
  5. magick_mind/client.py +188 -0
  6. magick_mind/config.py +28 -0
  7. magick_mind/exceptions.py +107 -0
  8. magick_mind/http/__init__.py +5 -0
  9. magick_mind/http/client.py +313 -0
  10. magick_mind/models/__init__.py +17 -0
  11. magick_mind/models/auth.py +30 -0
  12. magick_mind/models/common.py +32 -0
  13. magick_mind/models/errors.py +73 -0
  14. magick_mind/models/v1/__init__.py +83 -0
  15. magick_mind/models/v1/api_keys.py +115 -0
  16. magick_mind/models/v1/artifact.py +151 -0
  17. magick_mind/models/v1/chat.py +104 -0
  18. magick_mind/models/v1/corpus.py +82 -0
  19. magick_mind/models/v1/end_user.py +75 -0
  20. magick_mind/models/v1/history.py +94 -0
  21. magick_mind/models/v1/mindspace.py +130 -0
  22. magick_mind/models/v1/model.py +25 -0
  23. magick_mind/models/v1/project.py +73 -0
  24. magick_mind/realtime/__init__.py +5 -0
  25. magick_mind/realtime/client.py +202 -0
  26. magick_mind/realtime/handler.py +122 -0
  27. magick_mind/resources/README.md +201 -0
  28. magick_mind/resources/__init__.py +42 -0
  29. magick_mind/resources/base.py +31 -0
  30. magick_mind/resources/v1/__init__.py +19 -0
  31. magick_mind/resources/v1/api_keys.py +181 -0
  32. magick_mind/resources/v1/artifact.py +287 -0
  33. magick_mind/resources/v1/chat.py +120 -0
  34. magick_mind/resources/v1/corpus.py +156 -0
  35. magick_mind/resources/v1/end_user.py +181 -0
  36. magick_mind/resources/v1/history.py +88 -0
  37. magick_mind/resources/v1/mindspace.py +331 -0
  38. magick_mind/resources/v1/model.py +19 -0
  39. magick_mind/resources/v1/project.py +155 -0
  40. magick_mind/routes.py +76 -0
  41. magickmind-0.1.1.dist-info/METADATA +593 -0
  42. magickmind-0.1.1.dist-info/RECORD +43 -0
  43. magickmind-0.1.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,151 @@
1
+ """
2
+ Artifact models for Magick Mind SDK v1 API.
3
+
4
+ Provides Pydantic models for file upload and artifact management using
5
+ presigned S3 URLs and webhook-based completion confirmation.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Optional
11
+
12
+ from pydantic import BaseModel, ConfigDict, Field
13
+
14
+
15
+ class Artifact(BaseModel):
16
+ """
17
+ Canonical artifact model representing an uploaded file.
18
+
19
+ Artifacts are files (documents, images, etc.) uploaded to S3 and
20
+ associated with a corpus or other container in the bifrost backend.
21
+ """
22
+
23
+ model_config = ConfigDict(
24
+ extra="allow"
25
+ ) # Allow additional fields from API responses
26
+
27
+ id: str = Field(..., description="Unique artifact identifier")
28
+ bucket: str = Field(..., description="S3 bucket name")
29
+ key: str = Field(..., description="S3 object key")
30
+ s3_url: str = Field(..., description="S3 URL (s3://bucket/key)")
31
+ content_type: str = Field(..., description="MIME type of the artifact")
32
+ size_bytes: int = Field(..., description="Size in bytes")
33
+ etag: Optional[str] = Field(None, description="S3 ETag")
34
+ version_id: Optional[str] = Field(None, description="S3 version ID")
35
+ status: str = Field(
36
+ ..., description="Artifact status (uploaded, processing, ready, failed)"
37
+ )
38
+ corpus_id: Optional[str] = Field(None, description="Associated corpus ID")
39
+ end_user_id: Optional[str] = Field(
40
+ None, description="End user who uploaded the artifact"
41
+ )
42
+ created_by: Optional[str] = Field(
43
+ None, description="Account ID that created the artifact"
44
+ )
45
+ created_at: Optional[int] = Field(
46
+ None, description="Creation timestamp (unix seconds)"
47
+ )
48
+ updated_at: Optional[int] = Field(
49
+ None, description="Last update timestamp (unix seconds)"
50
+ )
51
+ error_code: Optional[str] = Field(
52
+ None, description="Error code if status is failed"
53
+ )
54
+
55
+
56
+ class PresignArtifactRequest(BaseModel):
57
+ """Request for obtaining a presigned S3 upload URL."""
58
+
59
+ file_name: str = Field(..., description="Name of the file to upload")
60
+ content_type: str = Field(..., description="MIME type of the file")
61
+ size_bytes: int = Field(..., description="File size in bytes", gt=0)
62
+ end_user_id: Optional[str] = Field(
63
+ None, description="End user identifier (optional)"
64
+ )
65
+ corpus_id: Optional[str] = Field(
66
+ None, description="Corpus to associate with (optional)"
67
+ )
68
+
69
+
70
+ class PresignArtifactResponse(BaseModel):
71
+ """
72
+ Response containing presigned upload URL and metadata.
73
+ """
74
+
75
+ success: Optional[bool] = Field(None, description="Request success status")
76
+ message: Optional[str] = Field(None, description="Response message")
77
+ id: Optional[str] = Field(None, description="Artifact ID (Relaxed)")
78
+ bucket: Optional[str] = Field(None, description="S3 bucket (Relaxed)")
79
+ key: Optional[str] = Field(None, description="S3 object key (Relaxed)")
80
+ s3_url: Optional[str] = Field(None, description="S3 URL (Relaxed)")
81
+ upload_url: Optional[str] = Field(None, description="Presigned PUT URL (Relaxed)")
82
+ expires_at: Optional[int] = Field(None, description="URL expiration time (Relaxed)")
83
+ required_headers: Optional[dict[str, str]] = Field(
84
+ None, description="HTTP headers (Relaxed)"
85
+ )
86
+
87
+
88
+ class GetArtifactResponse(BaseModel):
89
+ """Response for getting a single artifact by ID."""
90
+
91
+ success: bool = Field(..., description="Request success status")
92
+ message: str = Field(..., description="Response message")
93
+ artifact: Artifact = Field(..., description="The artifact data")
94
+
95
+
96
+ class ListArtifactsResponse(BaseModel):
97
+ """Response for listing/querying artifacts."""
98
+
99
+ success: bool = Field(..., description="Request success status")
100
+ message: str = Field(..., description="Response message")
101
+ artifacts: list[Artifact] = Field(..., description="List of artifacts")
102
+
103
+
104
+ class DeleteArtifactResponse(BaseModel):
105
+ """Response for deleting an artifact."""
106
+
107
+ success: bool = Field(..., description="Request success status")
108
+ message: str = Field(..., description="Response message")
109
+
110
+
111
+ class FinalizeArtifactRequest(BaseModel):
112
+ """
113
+ Client-driven finalize request (fallback when webhook is unavailable).
114
+ """
115
+
116
+ artifact_id: str = Field(..., description="Artifact ID")
117
+ bucket: str = Field(..., description="S3 bucket")
118
+ key: str = Field(..., description="S3 object key")
119
+ version_id: Optional[str] = Field(None, description="S3 version ID")
120
+ size_bytes: Optional[int] = Field(None, description="Actual uploaded size")
121
+ content_type: Optional[str] = Field(None, description="Content type")
122
+ etag: Optional[str] = Field(None, description="S3 ETag")
123
+ checksum_sha256: Optional[str] = Field(None, description="SHA256 checksum")
124
+
125
+
126
+ class FinalizeArtifactResponse(BaseModel):
127
+ """Response for finalize operation."""
128
+
129
+ success: Optional[bool] = Field(None, description="Request success status")
130
+ message: Optional[str] = Field(None, description="Response message")
131
+
132
+
133
+ class ArtifactWebhookPayload(BaseModel):
134
+ """
135
+ Webhook payload sent from S3 Lambda or client finalize.
136
+
137
+ This is the shape of data sent to the webhook endpoint after
138
+ an artifact upload is complete.
139
+ """
140
+
141
+ artifact_id: str = Field(..., description="Artifact ID")
142
+ corpus_id: Optional[str] = Field(None, description="Corpus ID if applicable")
143
+ bucket: str = Field(..., description="S3 bucket")
144
+ key: str = Field(..., description="S3 object key")
145
+ version_id: Optional[str] = Field(None, description="S3 version ID")
146
+ size_bytes: Optional[int] = Field(None, description="File size in bytes")
147
+ content_type: Optional[str] = Field(None, description="MIME type")
148
+ etag: Optional[str] = Field(None, description="S3 ETag")
149
+ checksum_sha256: Optional[str] = Field(None, description="SHA256 checksum")
150
+ status: str = Field(..., description="Status: uploaded, processing, ready, failed")
151
+ error_code: Optional[str] = Field(None, description="Error code if failed")
@@ -0,0 +1,104 @@
1
+ """V1 chat API models.
2
+
3
+ These models mirror the bifrost API types for /v1/magickmind/chat endpoint.
4
+ """
5
+
6
+ from typing import Optional
7
+
8
+ from pydantic import BaseModel, Field, field_serializer
9
+
10
+
11
+ class ConfigSchema(BaseModel):
12
+ """
13
+ Configuration for chat request.
14
+
15
+ Contains model selection and compute settings.
16
+ """
17
+
18
+ fast_model_id: str = Field(..., description="Model ID for fast brain")
19
+ smart_model_ids: list[str] = Field(..., description="Model IDs for smart brain")
20
+ compute_power: int = Field(default=0, description="Compute power setting (0-100)")
21
+
22
+
23
+ class ChatSendRequest(BaseModel):
24
+ """
25
+ Request to send a chat message to a mindspace.
26
+
27
+ Example:
28
+ request = ChatSendRequest(
29
+ api_key="sk-...",
30
+ mindspace_id="mind-123",
31
+ message="Hello!",
32
+ enduser_id="user-456",
33
+ config=ConfigSchema(
34
+ fast_model_id="gpt-4",
35
+ smart_model_ids=["gpt-4"],
36
+ compute_power=50,
37
+ ),
38
+ )
39
+ """
40
+
41
+ api_key: str = Field(..., description="API key for LLM access")
42
+ mindspace_id: str = Field(..., description="Mindspace/chat conversation ID")
43
+ message: str = Field(..., description="User message text to send")
44
+ enduser_id: str = Field(..., description="End-user identifier")
45
+ config: ConfigSchema = Field(..., description="Model configuration")
46
+ reply_to_message_id: Optional[str] = Field(
47
+ default=None, description="ID of message being replied to"
48
+ )
49
+ additional_context: Optional[str] = Field(
50
+ default=None, description="Additional context for the message"
51
+ )
52
+ artifact_ids: Optional[list[str]] = Field(
53
+ default=None, description="List of artifact IDs to attach to message"
54
+ )
55
+
56
+ # =========================================================================
57
+ # Serializers: Transform None → default values for API contract compliance
58
+ # SDK users can omit these fields, but API expects them in the payload
59
+ # =========================================================================
60
+
61
+ @field_serializer("artifact_ids")
62
+ def serialize_artifact_ids(self, v: list[str] | None) -> list[str]:
63
+ """API requires this field; default to empty list if not provided."""
64
+ return v or []
65
+
66
+
67
+ class ChatPayload(BaseModel):
68
+ """
69
+ Chat response payload schema.
70
+
71
+ Flexible data container for chat response with message metadata.
72
+ Can be extended to support various response formats.
73
+ """
74
+
75
+ message_id: Optional[str] = Field(
76
+ None, description="Generated message ID (Relaxed)"
77
+ )
78
+ task_id: Optional[str] = Field(None, description="Associated task ID (Relaxed)")
79
+ content: Optional[str] = Field(None, description="AI response text (Relaxed)")
80
+ reply_to: Optional[str] = Field(
81
+ default=None, description="ID of message being replied to"
82
+ )
83
+
84
+
85
+ class ChatSendResponse(BaseModel):
86
+ """
87
+ Response from sending a chat message.
88
+
89
+ Matches Bifrost ChatResponse structure with only content field.
90
+
91
+ Example:
92
+ {
93
+ "content": {
94
+ "message_id": "msg-789",
95
+ "task_id": "task-123",
96
+ "content": "Hello! How can I help you?",
97
+ "reply_to": null
98
+ }
99
+ }
100
+ """
101
+
102
+ content: Optional[ChatPayload] = Field(
103
+ default=None, description="Chat response payload"
104
+ )
@@ -0,0 +1,82 @@
1
+ """
2
+ Corpus models for Magick Mind SDK v1 API.
3
+
4
+ Provides Pydantic models for corpus (knowledge base) management.
5
+ Corpus represents a collection of artifacts that can be used for
6
+ RAG (Retrieval Augmented Generation) workflows.
7
+ """
8
+
9
+ from typing import TYPE_CHECKING, Optional
10
+
11
+ from pydantic import BaseModel, ConfigDict, Field
12
+
13
+ if TYPE_CHECKING:
14
+ from magick_mind.models.v1.end_user import PageInfo
15
+
16
+
17
+ class Corpus(BaseModel):
18
+ """
19
+ Canonical corpus model representing a knowledge base.
20
+
21
+ A corpus is a collection of artifacts (documents, files) that can be
22
+ used for semantic search and retrieval augmented generation.
23
+ """
24
+
25
+ model_config = ConfigDict(populate_by_name=True)
26
+
27
+ id: str = Field(..., description="Unique corpus identifier")
28
+ name: str = Field(..., description="Corpus name")
29
+ description: Optional[str] = Field(None, description="Corpus description")
30
+ artifact_ids: Optional[list[str]] = Field(
31
+ None, description="List of artifact IDs in this corpus"
32
+ )
33
+ created_by: Optional[str] = Field(
34
+ None, description="Account ID that created the corpus"
35
+ )
36
+ created_at: Optional[str] = Field(
37
+ None, description="Creation timestamp (ISO format)"
38
+ )
39
+ updated_at: Optional[str] = Field(
40
+ None, description="Last update timestamp (ISO format)"
41
+ )
42
+
43
+
44
+ class CreateCorpusRequest(BaseModel):
45
+ """Request for creating a new corpus."""
46
+
47
+ name: Optional[str] = Field(None, description="Corpus name (Relaxed)")
48
+ description: Optional[str] = Field(None, description="Corpus description (Relaxed)")
49
+ artifact_ids: Optional[list[str]] = Field(
50
+ None, description="Optional list of artifact IDs (Relaxed)"
51
+ )
52
+
53
+
54
+ class ListCorpusResponse(BaseModel):
55
+ """
56
+ Response for listing corpus.
57
+
58
+ Matches Bifrost's {data: list[Corpus], paging: PageInfo} structure.
59
+ """
60
+
61
+ data: list[Corpus] = Field(..., description="List of corpus")
62
+ paging: "PageInfo" = Field(..., description="Pagination information")
63
+
64
+
65
+ class UpdateCorpusRequest(BaseModel):
66
+ """Request for updating an existing corpus."""
67
+
68
+ name: Optional[str] = Field(None, description="Corpus name (Relaxed)")
69
+ description: Optional[str] = Field(None, description="Corpus description (Relaxed)")
70
+ artifact_ids: Optional[list[str]] = Field(
71
+ None, description="List of artifact IDs (Relaxed)"
72
+ )
73
+
74
+
75
+ class DeleteCorpusResponse:
76
+ """
77
+ Response for deleting a corpus.
78
+
79
+ Bifrost returns 204 No Content with no response body.
80
+ """
81
+
82
+ pass
@@ -0,0 +1,75 @@
1
+ """
2
+ End user models for Magick Mind SDK v1 API.
3
+
4
+ Mirrors Bifrost's /v1/end-users endpoint request/response schemas.
5
+ """
6
+
7
+ from typing import Optional
8
+
9
+ from pydantic import BaseModel, ConfigDict, Field
10
+
11
+ from magick_mind.models.common import Cursors, PageInfo
12
+
13
+
14
+ class EndUser(BaseModel):
15
+ """
16
+ End user schema from Bifrost.
17
+
18
+ Represents an end user in a multi-tenant agentic SaaS application.
19
+ """
20
+
21
+ model_config = ConfigDict(populate_by_name=True)
22
+
23
+ id: str = Field(..., description="End user ID")
24
+ name: str = Field(..., description="End user name")
25
+ external_id: Optional[str] = Field(
26
+ default=None,
27
+ description="Optional external ID for mapping to external systems",
28
+ )
29
+ tenant_id: str = Field(..., description="Tenant ID this end user belongs to")
30
+ created_by: Optional[str] = Field(default=None, description="User ID of creator")
31
+ updated_by: Optional[str] = Field(
32
+ default=None, description="User ID of last updater"
33
+ )
34
+ created_at: str = Field(..., description="Creation timestamp (ISO8601)")
35
+ updated_at: str = Field(..., description="Last update timestamp (ISO8601)")
36
+
37
+
38
+ class CreateEndUserRequest(BaseModel):
39
+ """
40
+ Request schema for creating a new end user.
41
+ """
42
+
43
+ name: str = Field(..., description="End user name (required)")
44
+ external_id: Optional[str] = Field(
45
+ default=None,
46
+ description="Optional external ID for mapping to external systems",
47
+ )
48
+ tenant_id: Optional[str] = Field(None, description="Tenant ID (Relaxed)")
49
+ actor_id: Optional[str] = Field(None, description="Actor ID (Relaxed)")
50
+
51
+
52
+ class QueryEndUserResponse(BaseModel):
53
+ """
54
+ Response schema for querying end users.
55
+
56
+ Uses new pagination pattern: {data: [], paging: {}}
57
+ """
58
+
59
+ data: list[EndUser] = Field(
60
+ default_factory=list, description="List of end users matching the query"
61
+ )
62
+ paging: PageInfo = Field(..., description="Pagination information")
63
+
64
+
65
+ class UpdateEndUserRequest(BaseModel):
66
+ """
67
+ Request schema for updating an end user.
68
+ """
69
+
70
+ name: Optional[str] = Field(default=None, description="End user name (optional)")
71
+ external_id: Optional[str] = Field(
72
+ default=None,
73
+ description="External ID for mapping to external systems (optional)",
74
+ )
75
+ tenant_id: Optional[str] = Field(None, description="Tenant ID (Relaxed)")
@@ -0,0 +1,94 @@
1
+ """
2
+ History models for Magick Mind SDK v1 API.
3
+
4
+ Mirrors Bifrost's /v1/mindspaces/messages endpoint response.
5
+ """
6
+
7
+ from typing import Optional
8
+
9
+ from pydantic import BaseModel, ConfigDict, Field
10
+
11
+ from magick_mind.models.common import Cursors, PageInfo
12
+
13
+
14
+ class ChatHistoryMessage(BaseModel):
15
+ """
16
+ Individual chat history message from Bifrost.
17
+
18
+ Maps to ChatHistoryItem from Bifrost's magickmind.api.
19
+ """
20
+
21
+ model_config = ConfigDict(populate_by_name=True)
22
+
23
+ id: Optional[str] = Field(None, description="Message ID")
24
+ mindspace_id: Optional[str] = Field(
25
+ None, description="Mindspace this message belongs to"
26
+ )
27
+ sent_by_user_id: Optional[str] = Field(
28
+ None, description="User who sent the message"
29
+ )
30
+ content: Optional[str] = Field(None, description="Message content/text")
31
+ reply_to_message_id: Optional[str] = Field(
32
+ default=None, description="ID of message being replied to"
33
+ )
34
+ status: Optional[str] = Field(None, description="Message status")
35
+ created_at: Optional[str] = Field(
36
+ None, alias="create_at", description="Creation timestamp (RFC3339)"
37
+ )
38
+ updated_at: Optional[str] = Field(
39
+ None, alias="update_at", description="Update timestamp (RFC3339)"
40
+ )
41
+
42
+
43
+ class HistoryResponse(BaseModel):
44
+ """
45
+ Response from Bifrost's /v1/mindspaces/messages endpoint.
46
+
47
+ Uses standardized Bifrost pagination format:
48
+ {
49
+ "data": [...],
50
+ "paging": {
51
+ "cursors": {"after": "...", "before": "..."},
52
+ "has_more": true,
53
+ "has_previous": false
54
+ }
55
+ }
56
+ """
57
+
58
+ data: list[ChatHistoryMessage] = Field(
59
+ default_factory=list, description="List of chat messages"
60
+ )
61
+ paging: PageInfo = Field(
62
+ default_factory=lambda: PageInfo(
63
+ cursors=Cursors(after=None, before=None),
64
+ has_more=False,
65
+ has_previous=False,
66
+ ),
67
+ description="Pagination information",
68
+ )
69
+
70
+ # Computed convenience properties for backward compatibility
71
+ @property
72
+ def chat_histories(self) -> list[ChatHistoryMessage]:
73
+ """Alias for data field (backward compatibility)."""
74
+ return self.data
75
+
76
+ @property
77
+ def has_more(self) -> bool:
78
+ """True if more messages exist forward."""
79
+ return self.paging.has_more
80
+
81
+ @property
82
+ def has_older(self) -> bool:
83
+ """True if more messages exist backward."""
84
+ return self.paging.has_previous
85
+
86
+ @property
87
+ def next_after_id(self) -> Optional[str]:
88
+ """Cursor for forward pagination."""
89
+ return self.paging.cursors.after if self.paging.cursors else None
90
+
91
+ @property
92
+ def next_before_id(self) -> Optional[str]:
93
+ """Cursor for backward pagination."""
94
+ return self.paging.cursors.before if self.paging.cursors else None
@@ -0,0 +1,130 @@
1
+ """V1 mindspace API models.
2
+
3
+ These models mirror the bifrost API types for /v1/mindspaces endpoint.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import Literal, Optional
9
+
10
+ from pydantic import BaseModel, Field
11
+
12
+ from magick_mind.models.common import BaseResponse
13
+ from magick_mind.models.v1.history import HistoryResponse
14
+
15
+
16
+ # Type alias for mindspace type enum (uppercase to match apidog)
17
+ MindSpaceType = Literal["PRIVATE", "GROUP"]
18
+
19
+
20
+ class MindSpace(BaseModel):
21
+ """
22
+ Mindspace schema model.
23
+
24
+ Represents a mindspace container that can be private (single user)
25
+ or group (multiple users), with attached corpus for knowledge.
26
+
27
+ Example:
28
+ {
29
+ "id": "mind-123",
30
+ "name": "Engineering Team",
31
+ "description": "Team workspace",
32
+ "project_id": "proj-456",
33
+ "corpus_ids": ["corp-1", "corp-2"],
34
+ "user_ids": ["user-1", "user-2"],
35
+ "type": "GROUP",
36
+ "created_by": "user-1",
37
+ "updated_by": "user-1",
38
+ "created_at": "2025-12-16T09:00:00Z",
39
+ "updated_at": "2025-12-16T09:00:00Z"
40
+ }
41
+ """
42
+
43
+ id: str = Field(..., description="Mindspace ID")
44
+ name: str = Field(..., description="Mindspace name")
45
+ description: Optional[str] = Field(None, description="Mindspace description")
46
+ project_id: str = Field(..., description="Associated project ID")
47
+ corpus_ids: Optional[list[str]] = Field(
48
+ None,
49
+ description="List of corpus IDs attached to this mindspace",
50
+ )
51
+ user_ids: Optional[list[str]] = Field(
52
+ None,
53
+ description="List of user IDs with access to this mindspace",
54
+ )
55
+ type: MindSpaceType = Field(..., description="Mindspace type: 'PRIVATE' or 'GROUP'")
56
+ created_by: Optional[str] = Field(
57
+ None, description="User ID who created the mindspace"
58
+ )
59
+ updated_by: Optional[str] = Field(
60
+ None, description="User ID who last updated the mindspace"
61
+ )
62
+ created_at: Optional[str] = Field(None, description="Creation timestamp (RFC3339)")
63
+ updated_at: Optional[str] = Field(
64
+ None, description="Last update timestamp (RFC3339)"
65
+ )
66
+
67
+
68
+ class CreateMindSpaceRequest(BaseModel):
69
+ """
70
+ Request to create a new mindspace.
71
+ """
72
+
73
+ name: Optional[str] = Field(
74
+ None, description="Mindspace name (Relaxed)", max_length=100
75
+ )
76
+ type: Optional[MindSpaceType] = Field(None, description="Mindspace type (Relaxed)")
77
+ description: Optional[str] = Field(
78
+ default=None, description="Mindspace description", max_length=256
79
+ )
80
+ project_id: Optional[str] = Field(default=None, description="Associated project ID")
81
+ corpus_ids: list[str] = Field(
82
+ default_factory=list, description="List of corpus IDs to attach"
83
+ )
84
+ user_ids: list[str] = Field(
85
+ default_factory=list, description="List of user IDs to grant access"
86
+ )
87
+
88
+
89
+ class GetMindSpaceListResponse(BaseModel):
90
+ """
91
+ Response from listing mindspaces.
92
+ """
93
+
94
+ mindspaces: list[MindSpace] = Field(
95
+ default_factory=list, description="List of mindspaces"
96
+ )
97
+
98
+
99
+ class UpdateMindSpaceRequest(BaseModel):
100
+ """
101
+ Request to update an existing mindspace.
102
+ """
103
+
104
+ name: Optional[str] = Field(
105
+ None, description="Mindspace name (Relaxed)", max_length=100
106
+ )
107
+ description: Optional[str] = Field(
108
+ default=None, description="Mindspace description", max_length=256
109
+ )
110
+ project_id: Optional[str] = Field(default=None, description="Associated project ID")
111
+ corpus_ids: list[str] = Field(
112
+ default_factory=list, description="List of corpus IDs to attach"
113
+ )
114
+ user_ids: list[str] = Field(
115
+ default_factory=list, description="List of user IDs to grant access"
116
+ )
117
+
118
+
119
+ class AddMindSpaceUsersRequest(BaseModel):
120
+ """
121
+ Request to add users to an existing mindspace.
122
+ """
123
+
124
+ user_ids: list[str] = Field(
125
+ ..., description="List of user IDs to add to the mindspace"
126
+ )
127
+
128
+
129
+ # Reuse HistoryResponse for messages endpoint since it's the same structure
130
+ MindspaceMessagesResponse = HistoryResponse
@@ -0,0 +1,25 @@
1
+ from typing import List, Optional
2
+ from pydantic import BaseModel, Field
3
+
4
+
5
+ class Model(BaseModel):
6
+ """Model information"""
7
+
8
+ id: Optional[str] = Field(None, description="The model identifier, e.g. 'gpt-4o'")
9
+ object: str = Field("model", description="The object type, always 'model'")
10
+ created: Optional[int] = Field(
11
+ None, description="The unix timestamp when the model was created"
12
+ )
13
+ owned_by: Optional[str] = Field(
14
+ None, description="The organization that owns the model"
15
+ )
16
+ provider: Optional[str] = Field(None, description="The provider of the model")
17
+
18
+
19
+ class ModelsListResponse(BaseModel):
20
+ """Response containing a list of models"""
21
+
22
+ object: str = Field("list", description="The object type, always 'list'")
23
+ data: List[Model] = Field(
24
+ default_factory=list, description="The list of available models"
25
+ )