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.
- magick_mind/__init__.py +39 -0
- magick_mind/auth/__init__.py +9 -0
- magick_mind/auth/base.py +46 -0
- magick_mind/auth/email_password.py +268 -0
- magick_mind/client.py +188 -0
- magick_mind/config.py +28 -0
- magick_mind/exceptions.py +107 -0
- magick_mind/http/__init__.py +5 -0
- magick_mind/http/client.py +313 -0
- magick_mind/models/__init__.py +17 -0
- magick_mind/models/auth.py +30 -0
- magick_mind/models/common.py +32 -0
- magick_mind/models/errors.py +73 -0
- magick_mind/models/v1/__init__.py +83 -0
- magick_mind/models/v1/api_keys.py +115 -0
- magick_mind/models/v1/artifact.py +151 -0
- magick_mind/models/v1/chat.py +104 -0
- magick_mind/models/v1/corpus.py +82 -0
- magick_mind/models/v1/end_user.py +75 -0
- magick_mind/models/v1/history.py +94 -0
- magick_mind/models/v1/mindspace.py +130 -0
- magick_mind/models/v1/model.py +25 -0
- magick_mind/models/v1/project.py +73 -0
- magick_mind/realtime/__init__.py +5 -0
- magick_mind/realtime/client.py +202 -0
- magick_mind/realtime/handler.py +122 -0
- magick_mind/resources/README.md +201 -0
- magick_mind/resources/__init__.py +42 -0
- magick_mind/resources/base.py +31 -0
- magick_mind/resources/v1/__init__.py +19 -0
- magick_mind/resources/v1/api_keys.py +181 -0
- magick_mind/resources/v1/artifact.py +287 -0
- magick_mind/resources/v1/chat.py +120 -0
- magick_mind/resources/v1/corpus.py +156 -0
- magick_mind/resources/v1/end_user.py +181 -0
- magick_mind/resources/v1/history.py +88 -0
- magick_mind/resources/v1/mindspace.py +331 -0
- magick_mind/resources/v1/model.py +19 -0
- magick_mind/resources/v1/project.py +155 -0
- magick_mind/routes.py +76 -0
- magickmind-0.1.1.dist-info/METADATA +593 -0
- magickmind-0.1.1.dist-info/RECORD +43 -0
- magickmind-0.1.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: magickmind
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Official Python SDK for the MagickMind AI platform.
|
|
5
|
+
Project-URL: Homepage, https://magickmind.ai/
|
|
6
|
+
Project-URL: Documentation, https://docs.magickmind.ai/
|
|
7
|
+
Project-URL: Repository, https://github.com/General-Magick-Industries/py-magickmind
|
|
8
|
+
Project-URL: Issues, https://github.com/General-Magick-Industries/py-magickmind/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/General-Magick-Industries/py-magickmind/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: Adrian <adrian@magickmind.ai>, Minnie <minnie@magickmind.ai>, Turtle <turtle@magickmind.ai>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
Keywords: ai,api,client,magickmind,sdk
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Requires-Dist: centrifuge-python>=0.4.2
|
|
23
|
+
Requires-Dist: httpx>=0.27.0
|
|
24
|
+
Requires-Dist: jwt>=1.4.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Requires-Dist: pytest-asyncio>=1.3.0
|
|
27
|
+
Requires-Dist: python-dotenv>=1.2.1
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: openapi-core>=0.19.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-mock>=3.12.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# Magick Mind SDK
|
|
36
|
+
|
|
37
|
+
Python SDK for seamless integration with the Magick Mind platform (Bifrost). This SDK provides type-safe, validated access to Bifrost's chat, mindspace, and realtime features.
|
|
38
|
+
|
|
39
|
+
> [!IMPORTANT]
|
|
40
|
+
> **Backend-Only SDK**
|
|
41
|
+
> This SDK is designed for **server-side applications only** and requires service-level authentication. It cannot be used directly by end users in browsers or mobile apps.
|
|
42
|
+
>
|
|
43
|
+
> **Architecture:** End Users → Your Backend (+ SDK) → Bifrost
|
|
44
|
+
> See [Backend Architecture Guide](docs/architecture/backend_architecture.md) for details.
|
|
45
|
+
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
- 🔐 **Authentication**: Secure login with email/password
|
|
49
|
+
- 💬 **Chat**: Type-safe chat resource with Pydantic validation
|
|
50
|
+
- 🧠 **Mindspaces**: Manage AI reasoning contexts and conversations
|
|
51
|
+
- 📡 **Realtime**: WebSocket client for live AI responses with deduplication
|
|
52
|
+
- 🔑 **Typed Resources**: Mindspaces, Projects, Corpus, API Keys, Artifacts, End Users, History
|
|
53
|
+
- ✅ **Validation**: Automatic request/response validation with Pydantic
|
|
54
|
+
- 🎯 **Developer Experience**: Clean, intuitive API design
|
|
55
|
+
- Desktop applications (PyQt, Tkinter, wxPython)
|
|
56
|
+
- CLI tools and automation scripts
|
|
57
|
+
- Server-side scripts
|
|
58
|
+
- **Robotics/IoT (Self-Service)**: Single device authenticates and subscribes to its own channel
|
|
59
|
+
|
|
60
|
+
**For web/mobile frontends:** If you're building browser-based apps or native mobile apps, you would need JavaScript, Swift, or Kotlin SDKs (not yet available). This Python SDK is for your backend.
|
|
61
|
+
|
|
62
|
+
**Common architecture:**
|
|
63
|
+
```
|
|
64
|
+
[Your Frontend/App] ←→ [Your Backend + This SDK] ←→ [Bifrost SaaS]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Robotics/IoT (Self-Service):**
|
|
68
|
+
```
|
|
69
|
+
[Robot/Device with SDK] ←→ [Bifrost SaaS]
|
|
70
|
+
```
|
|
71
|
+
In this pattern, the device authenticates as itself and subscribes to its own channel. See [Event-Driven Patterns](docs/architecture/event_driven_patterns.md#self-service-pattern-roboticsiot) for details.
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
Using `uv` (recommended):
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
cd AGD_Magick_Mind_SDK
|
|
80
|
+
uv sync
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Using pip:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
cd AGD_Magick_Mind_SDK
|
|
87
|
+
pip install -e .
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Core Concepts
|
|
91
|
+
|
|
92
|
+
### Mindspaces: The Central Hub
|
|
93
|
+
|
|
94
|
+
**Mindspace is the central organizing concept in Bifrost** - it's where conversations, knowledge, and collaboration converge. When designing your application architecture, start by thinking about mindspaces:
|
|
95
|
+
|
|
96
|
+
- **All chat conversations happen within a mindspace**
|
|
97
|
+
- **Knowledge (corpus) attaches to mindspaces** to provide context for AI responses
|
|
98
|
+
- **Users collaborate through mindspaces** (private for individuals, group for teams)
|
|
99
|
+
- **Everything connects through mindspaces** - projects, messages, artifacts
|
|
100
|
+
|
|
101
|
+
```mermaid
|
|
102
|
+
graph LR
|
|
103
|
+
U[Users] --> MS[Mindspace]
|
|
104
|
+
C[Corpus/Knowledge] --> MS
|
|
105
|
+
MS --> Chat[Conversations]
|
|
106
|
+
MS --> History[Message History]
|
|
107
|
+
P[Projects] -.organize.-> MS
|
|
108
|
+
|
|
109
|
+
style MS fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,color:#fff
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Architectural Implication**: When building with Bifrost, most operations reference a `mindspace_id`. This is by design - mindspaces provide the context and scope for AI interactions.
|
|
113
|
+
|
|
114
|
+
📖 **Learn more:** [Mindspace Resource Guide](docs/resources/mindspace.md)
|
|
115
|
+
|
|
116
|
+
## Quick Start
|
|
117
|
+
|
|
118
|
+
### Authentication
|
|
119
|
+
|
|
120
|
+
The SDK uses **email/password authentication** which calls bifrost's `/v1/auth/login` endpoint:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from magick_mind import MagickMind
|
|
124
|
+
|
|
125
|
+
# Create client with email/password
|
|
126
|
+
client = MagickMind(
|
|
127
|
+
email="user@example.com",
|
|
128
|
+
password="your_password",
|
|
129
|
+
base_url="https://bifrost.example.com"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Authentication happens automatically on first API call
|
|
133
|
+
# Tokens are automatically refreshed when needed
|
|
134
|
+
print(f"Authenticated: {client.is_authenticated()}")
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
> **Note**: The `api_key` you might see in chat requests is **not for SDK authentication**.
|
|
138
|
+
> It's a parameter you pass when calling LLM endpoints (for tracking/billing).
|
|
139
|
+
> The SDK itself authenticates with JWT tokens from `/v1/auth/login`.
|
|
140
|
+
|
|
141
|
+
### Making API Calls
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
# Once authenticated, use the HTTP client to make requests
|
|
145
|
+
# The client automatically adds authentication headers
|
|
146
|
+
|
|
147
|
+
# POST request
|
|
148
|
+
response = client.http.post(
|
|
149
|
+
"/v1/magickmind/chat",
|
|
150
|
+
json={
|
|
151
|
+
"api_key": "sk-your-llm-key",
|
|
152
|
+
"message": "Hello!",
|
|
153
|
+
"chat_id": "chat-123",
|
|
154
|
+
"sender_id": "user-456"
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# GET request
|
|
159
|
+
response = client.http.get("/v1/some-endpoint")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Context Manager
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# Use as context manager for automatic cleanup
|
|
166
|
+
with MagickMind(email="user@example.com", password="pass", base_url="...") as client:
|
|
167
|
+
response = client.http.get("/v1/endpoint")
|
|
168
|
+
# Client automatically closes when exiting context
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## HTTP Client for Power Users
|
|
172
|
+
|
|
173
|
+
The `client.http` property provides direct access to the authenticated HTTP client. This is intended for:
|
|
174
|
+
|
|
175
|
+
**Bifrost Developers:**
|
|
176
|
+
- Testing new endpoints before implementing resources
|
|
177
|
+
- Experimenting with beta/experimental features
|
|
178
|
+
- Quick prototyping
|
|
179
|
+
|
|
180
|
+
**Power Users:**
|
|
181
|
+
- Direct API access without waiting for typed resources
|
|
182
|
+
- One-off calls or custom integrations
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
# Test experimental endpoint
|
|
186
|
+
response = client.http.post(
|
|
187
|
+
"/beta/new-feature",
|
|
188
|
+
json={"test": "data"}
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Mix versions in same app
|
|
192
|
+
v1_response = client.http.post("/v1/magickmind/chat", json={...})
|
|
193
|
+
beta_response = client.http.post("/beta/magickmind/chat", json={...})
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The HTTP client automatically handles:
|
|
197
|
+
- ✅ Authentication token injection
|
|
198
|
+
- ✅ Token refresh when expired
|
|
199
|
+
- ✅ Error mapping to SDK exceptions
|
|
200
|
+
- ✅ Same configuration as main client
|
|
201
|
+
|
|
202
|
+
## Authentication
|
|
203
|
+
|
|
204
|
+
The SDK uses **email/password authentication** with JWT tokens:
|
|
205
|
+
|
|
206
|
+
Uses bifrost's `/v1/auth/login` endpoint. Automatically handles:
|
|
207
|
+
- Initial login
|
|
208
|
+
- Token caching
|
|
209
|
+
- Automatic token refresh using refresh_token
|
|
210
|
+
- Re-authentication when refresh token expires
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
client = MagickMind(
|
|
214
|
+
email="your@email.com",
|
|
215
|
+
password="your_password",
|
|
216
|
+
base_url="https://bifrost.example.com"
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### About API Keys
|
|
221
|
+
|
|
222
|
+
If you see `api_key` in documentation or code examples, note that this is **NOT for authenticating the SDK**.
|
|
223
|
+
The `api_key` is a parameter you pass when calling specific endpoints (like chat) for LLM access:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
# SDK authenticates with email/password (JWT)
|
|
227
|
+
client = MagickMind(email="...", password="...", base_url="...")
|
|
228
|
+
|
|
229
|
+
# api_key is passed as a parameter to LLM endpoints
|
|
230
|
+
# response = client.chat(api_key="your-llm-api-key", message="Hello")
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
## Examples
|
|
235
|
+
|
|
236
|
+
See the `examples/` directory for complete working examples:
|
|
237
|
+
|
|
238
|
+
- `examples/email_password_auth.py` - Email/password with auto-refresh
|
|
239
|
+
- `examples/backend_service.py` - Production-ready backend service pattern
|
|
240
|
+
- `examples/chat_example.py` - Using the typed chat resource
|
|
241
|
+
|
|
242
|
+
Run example:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Set environment variables
|
|
246
|
+
export BIFROST_BASE_URL="http://localhost:8888"
|
|
247
|
+
export BIFROST_EMAIL="user@example.com"
|
|
248
|
+
export BIFROST_PASSWORD="your_password"
|
|
249
|
+
|
|
250
|
+
# Run example
|
|
251
|
+
uv run python examples/email_password_auth.py
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Backend Integration
|
|
255
|
+
|
|
256
|
+
If you're building a **backend service** that uses this SDK as middleware (e.g., your backend receives data from Bifrost and manages state for your own frontend), see:
|
|
257
|
+
|
|
258
|
+
📖 **[Backend Integration Guide](docs/guides/backend_integration.md)**
|
|
259
|
+
|
|
260
|
+
Covers production patterns for:
|
|
261
|
+
- Message deduplication
|
|
262
|
+
- Hybrid realtime + HTTP sync
|
|
263
|
+
- Recovery from disconnects
|
|
264
|
+
- Reliable message processing
|
|
265
|
+
|
|
266
|
+
Example backend service:
|
|
267
|
+
```python
|
|
268
|
+
from magick_mind import MagickMind
|
|
269
|
+
from examples.backend_service import ChatBackendService
|
|
270
|
+
|
|
271
|
+
client = MagickMind(email="...", password="...", base_url="...")
|
|
272
|
+
service = ChatBackendService(client)
|
|
273
|
+
|
|
274
|
+
# Handles realtime events + periodic sync for reliability
|
|
275
|
+
await service.start(mindspace_id="mind-123", user_id="service-user")
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Event-Driven Architecture
|
|
279
|
+
|
|
280
|
+
The SDK supports event-driven patterns with both realtime WebSocket events and HTTP APIs.
|
|
281
|
+
|
|
282
|
+
📖 **[Event-Driven Patterns Guide](docs/architecture/event_driven_patterns.md)**
|
|
283
|
+
|
|
284
|
+
Learn about:
|
|
285
|
+
- Events as source of truth (current Bifrost)
|
|
286
|
+
- Events as notifications (industry standard)
|
|
287
|
+
- Hybrid approaches for production
|
|
288
|
+
- Migration paths
|
|
289
|
+
|
|
290
|
+
## Realtime WebSocket Client
|
|
291
|
+
|
|
292
|
+
The SDK provides a powerful realtime client for receiving live updates via WebSocket. This is essential for building reactive applications that need instant notifications.
|
|
293
|
+
|
|
294
|
+
### Quick Example
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
import asyncio
|
|
298
|
+
from magick_mind import MagickMind
|
|
299
|
+
from magick_mind.realtime.handler import RealtimeEventHandler
|
|
300
|
+
|
|
301
|
+
class MyHandler(RealtimeEventHandler):
|
|
302
|
+
async def on_message(self, user_id: str, payload):
|
|
303
|
+
# Automatically receives parsed messages
|
|
304
|
+
print(f"Update for {user_id}: {payload}")
|
|
305
|
+
|
|
306
|
+
async def main():
|
|
307
|
+
client = MagickMind(
|
|
308
|
+
email="user@example.com",
|
|
309
|
+
password="password",
|
|
310
|
+
base_url="https://bifrost.example.com",
|
|
311
|
+
ws_endpoint="wss://bifrost.example.com/connection/websocket"
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
# Connect with handler
|
|
315
|
+
await client.realtime.connect(events=MyHandler())
|
|
316
|
+
|
|
317
|
+
# Subscribe to users (creates per-user channels)
|
|
318
|
+
await client.realtime.subscribe_many(["user-1", "user-2", "user-3"])
|
|
319
|
+
|
|
320
|
+
# Keep listening...
|
|
321
|
+
await asyncio.sleep(60)
|
|
322
|
+
|
|
323
|
+
asyncio.run(main())
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Key Features
|
|
327
|
+
|
|
328
|
+
- **Per-User Subscriptions** - Each user gets their own secure channel
|
|
329
|
+
- **Bulk Operations** - `subscribe_many()` for handling 100s of users efficiently
|
|
330
|
+
- **Auto-Reconnect** - Centrifugo handles connection recovery automatically
|
|
331
|
+
- **Type-Safe Handlers** - `RealtimeEventHandler` provides clean callback interface
|
|
332
|
+
|
|
333
|
+
### Architecture: Per-User Pattern
|
|
334
|
+
|
|
335
|
+
When building relay services or multi-user applications, the SDK uses a **per-user subscription model**:
|
|
336
|
+
|
|
337
|
+
- **500 users = 500 subscriptions** (not 1 room channel)
|
|
338
|
+
- Each user has an isolated subscription
|
|
339
|
+
- Ensures privacy, security, and efficient server-side filtering
|
|
340
|
+
- Single WebSocket connection multiplexes all subscriptions
|
|
341
|
+
|
|
342
|
+
**Why 500 subscriptions is correct:**
|
|
343
|
+
- 🔒 Security: Users can't see each other's data
|
|
344
|
+
- 📊 Efficiency: Server only sends relevant messages
|
|
345
|
+
- 📈 Scalable: Centrifugo handles millions of channels
|
|
346
|
+
|
|
347
|
+
📖 **[Complete Realtime Guide](docs/realtime_guide.md)** - Covers subscription patterns, bulk operations, error handling, and relay service architecture.
|
|
348
|
+
|
|
349
|
+
## Extending the SDK
|
|
350
|
+
|
|
351
|
+
The SDK currently provides authentication and HTTP client foundation. Want to add typed resource clients (e.g., `client.chat.send(...)`)?
|
|
352
|
+
|
|
353
|
+
See **[docs/contributing/resource_implementation_guide/](docs/contributing/resource_implementation_guide/)** for a complete reference implementation showing:
|
|
354
|
+
|
|
355
|
+
- ✅ Pydantic models for request/response validation
|
|
356
|
+
- ✅ Version-aware resource classes (v1, v2)
|
|
357
|
+
- ✅ Clean namespace pattern (`client.v1.chat`, `client.v2.chat`)
|
|
358
|
+
- ✅ Working usage examples
|
|
359
|
+
|
|
360
|
+
This serves as a template for adding chat, history, users, or any other resources to the SDK.
|
|
361
|
+
|
|
362
|
+
## Future Plans
|
|
363
|
+
|
|
364
|
+
### Versioned Resources
|
|
365
|
+
|
|
366
|
+
When resources are implemented, they will follow a namespace pattern:
|
|
367
|
+
|
|
368
|
+
```python
|
|
369
|
+
client = MagickMind(...)
|
|
370
|
+
|
|
371
|
+
# Explicit version access
|
|
372
|
+
client.v1.chat.send(...) # Always v1 (stable)
|
|
373
|
+
client.v2.chat.send(...) # Always v2 (new features)
|
|
374
|
+
client.beta.chat.send(...) # Beta/experimental
|
|
375
|
+
|
|
376
|
+
# Mix and match versions
|
|
377
|
+
client.v1.history.list(...) # Use stable for some endpoints
|
|
378
|
+
client.beta.chat.send(...) # Test beta for others
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Key principles:**
|
|
382
|
+
- **Explicit over implicit** - Users choose exact version
|
|
383
|
+
- **Type safe** - Each version has different request/response types
|
|
384
|
+
- **Mix-and-match** - Can use different versions for different endpoints
|
|
385
|
+
- **Sparse coverage** - Only implement resources that exist in bifrost
|
|
386
|
+
- Example: If `/beta/chat` exists but `/beta/history` doesn't, `client.beta` only has `chat`
|
|
387
|
+
|
|
388
|
+
**Why this approach:**
|
|
389
|
+
- Safe gradual migration (v1 → v2)
|
|
390
|
+
- Test breaking changes before full adoption
|
|
391
|
+
- Clear which version you're using
|
|
392
|
+
- No surprises when SDK updates
|
|
393
|
+
|
|
394
|
+
### Example Usage Scenarios
|
|
395
|
+
|
|
396
|
+
**Scenario 1: Production app using stable v1**
|
|
397
|
+
```python
|
|
398
|
+
client = MagickMind(...)
|
|
399
|
+
|
|
400
|
+
# All endpoints use v1
|
|
401
|
+
response = client.v1.chat.send(...)
|
|
402
|
+
history = client.v1.history.list(...)
|
|
403
|
+
user = client.v1.users.get(...)
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
**Scenario 2: Testing beta chat, keeping others stable**
|
|
407
|
+
```python
|
|
408
|
+
client = MagickMind(...)
|
|
409
|
+
|
|
410
|
+
# Test new chat features
|
|
411
|
+
response = client.beta.chat.send(
|
|
412
|
+
message="...",
|
|
413
|
+
temperature=0.8, # New parameter in beta
|
|
414
|
+
context={...} # New context support
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
# Keep other endpoints stable
|
|
418
|
+
history = client.v1.history.list(...)
|
|
419
|
+
user = client.v1.users.get(...)
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
**Scenario 3: Gradual migration v1 → v2**
|
|
423
|
+
```python
|
|
424
|
+
# Week 1: Start migrating chat to v2
|
|
425
|
+
response = client.v2.chat.send(...) # Migrated
|
|
426
|
+
history = client.v1.history.list(...) # Still v1
|
|
427
|
+
|
|
428
|
+
# Week 2: Migrate more endpoints
|
|
429
|
+
history = client.v2.history.list(...) # Migrated
|
|
430
|
+
user = client.v1.users.get(...) # Still v1
|
|
431
|
+
|
|
432
|
+
# Week 3: Fully migrated
|
|
433
|
+
# All endpoints now use v2
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Scenario 4: Bifrost dev testing experimental endpoint**
|
|
437
|
+
```python
|
|
438
|
+
client = MagickMind(...)
|
|
439
|
+
|
|
440
|
+
# Test endpoint that doesn't have resource yet
|
|
441
|
+
response = client.http.post(
|
|
442
|
+
"/experimental/ai-agents",
|
|
443
|
+
json={"task": "analyze data"}
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
# Use typed resources for stable endpoints
|
|
447
|
+
chat = client.v1.chat.send(...)
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### Default Shortcuts (Future)
|
|
451
|
+
|
|
452
|
+
For convenience, SDK may add `client.chat` shortcuts that point to a default version:
|
|
453
|
+
|
|
454
|
+
**SDK 1.x series:**
|
|
455
|
+
```python
|
|
456
|
+
client = MagickMind(...)
|
|
457
|
+
|
|
458
|
+
# Shortcuts point to v1 (stable)
|
|
459
|
+
client.chat.send(...) # → client.v1.chat.send(...)
|
|
460
|
+
client.history.list(...) # → client.v1.history.list(...)
|
|
461
|
+
|
|
462
|
+
# Explicit always available
|
|
463
|
+
client.v1.chat.send(...) # Explicit v1
|
|
464
|
+
client.v2.chat.send(...) # Explicit v2 (when available)
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
**SDK 2.x series (breaking change):**
|
|
468
|
+
```python
|
|
469
|
+
client = MagickMind(...)
|
|
470
|
+
|
|
471
|
+
# Shortcuts now point to v2 (BREAKING!)
|
|
472
|
+
client.chat.send(...) # → client.v2.chat.send(...)
|
|
473
|
+
|
|
474
|
+
# Explicit v1 still works
|
|
475
|
+
client.v1.chat.send(...) # Pin to v1 for stability
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
**Best practice:** Use explicit versions (`client.v1.chat`) for production code that needs stability.
|
|
479
|
+
|
|
480
|
+
### Deprecation and Migration
|
|
481
|
+
|
|
482
|
+
When bifrost deprecates an API version, SDK will follow this pattern:
|
|
483
|
+
|
|
484
|
+
**Phase 1: Deprecation Warning**
|
|
485
|
+
```python
|
|
486
|
+
# SDK 1.5: v1 still works but warns
|
|
487
|
+
response = client.v1.chat.send(...)
|
|
488
|
+
# Warning: v1 chat API is deprecated, migrate to v2 by 2025-06-01
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
**Phase 2: Both Versions Co-exist**
|
|
492
|
+
```python
|
|
493
|
+
# SDK 1.x: Both v1 and v2 available
|
|
494
|
+
client.v1.chat.send(...) # Deprecated but works
|
|
495
|
+
client.v2.chat.send(...) # Recommended
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
**Phase 3: Removal in Next Major Version**
|
|
499
|
+
```python
|
|
500
|
+
# SDK 2.0: v1 removed
|
|
501
|
+
client.v1.chat.send(...) # ❌ AttributeError
|
|
502
|
+
client.v2.chat.send(...) # ✅ Works
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
**Migration guide provided in CHANGELOG for each breaking change.**
|
|
506
|
+
|
|
507
|
+
## Error Handling
|
|
508
|
+
|
|
509
|
+
The SDK provides specific exceptions for different error scenarios:
|
|
510
|
+
|
|
511
|
+
```python
|
|
512
|
+
from magick_mind import (
|
|
513
|
+
MagickMind,
|
|
514
|
+
AuthenticationError,
|
|
515
|
+
TokenExpiredError,
|
|
516
|
+
ProblemDetailsException,
|
|
517
|
+
ValidationError,
|
|
518
|
+
RateLimitError
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
try:
|
|
522
|
+
client = MagickMind(email="user@example.com", password="wrong", base_url="...")
|
|
523
|
+
response = client.http.get("/v1/endpoint")
|
|
524
|
+
except AuthenticationError as e:
|
|
525
|
+
print(f"Authentication failed: {e}")
|
|
526
|
+
except TokenExpiredError as e:
|
|
527
|
+
print(f"Token expired: {e}")
|
|
528
|
+
except RateLimitError as e:
|
|
529
|
+
print(f"Rate limited: {e}")
|
|
530
|
+
except ValidationError as e:
|
|
531
|
+
# Handle field-level validation errors (400 Bad Request)
|
|
532
|
+
print(f"Validation error: {e.detail}")
|
|
533
|
+
for field, errors in e.get_field_errors().items():
|
|
534
|
+
print(f" {field}: {', '.join(errors)}")
|
|
535
|
+
except ProblemDetailsException as e:
|
|
536
|
+
# Handle other API errors (RFC 7807 Problem Details)
|
|
537
|
+
print(f"API error: {e.title} - {e.detail}")
|
|
538
|
+
print(f"Request ID: {e.request_id}") # For support tickets
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### Error Quick Reference
|
|
542
|
+
|
|
543
|
+
| Exception | Typical Cause | Key Attributes | Recovery Action |
|
|
544
|
+
|-----------|---------------|----------------|-----------------|
|
|
545
|
+
| `AuthenticationError` | Invalid credentials | `message`, `status_code` | Check email/password and re-authenticate |
|
|
546
|
+
| `TokenExpiredError` | Token expired | `message` | Auto-refreshed by SDK transparently |
|
|
547
|
+
| `ValidationError` | Bad request data | `get_field_errors()`, `request_id` | Fix input using field error details |
|
|
548
|
+
| `ProblemDetailsException` | API error (4xx, 5xx) | `status`, `title`, `detail`, `request_id` | Check detail message and request_id |
|
|
549
|
+
| `RateLimitError` | Rate limit exceeded | `status_code` (429) | Retry with exponential backoff |
|
|
550
|
+
|
|
551
|
+
> [!IMPORTANT]
|
|
552
|
+
> **Always log `request_id`** from `ProblemDetailsException` - it's essential for support tickets and debugging with the Bifrost team.
|
|
553
|
+
|
|
554
|
+
📖 **[Complete Error Handling Guide](docs/guides/error_handling.md)** - Comprehensive guide with error catalog, retry patterns, and production examples.
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
## Configuration
|
|
558
|
+
|
|
559
|
+
Customize SDK behavior:
|
|
560
|
+
|
|
561
|
+
```python
|
|
562
|
+
client = MagickMind(
|
|
563
|
+
email="user@example.com",
|
|
564
|
+
password="password",
|
|
565
|
+
base_url="https://bifrost.example.com",
|
|
566
|
+
timeout=60.0, # Request timeout in seconds (default: 30.0)
|
|
567
|
+
verify_ssl=True # Verify SSL certificates (default: True)
|
|
568
|
+
)
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
## Development
|
|
572
|
+
|
|
573
|
+
### Install development dependencies
|
|
574
|
+
|
|
575
|
+
```bash
|
|
576
|
+
uv sync --all-extras
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Run tests
|
|
580
|
+
|
|
581
|
+
```bash
|
|
582
|
+
uv run pytest tests/ -v
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
## License
|
|
586
|
+
|
|
587
|
+
MIT License - see LICENSE file for details.
|
|
588
|
+
|
|
589
|
+
## Authors
|
|
590
|
+
|
|
591
|
+
- Adrian (minoak@globalmagicko.com)
|
|
592
|
+
- Turtle (turtle@globalmagicko.com)
|
|
593
|
+
- Min Thu Wai (minthu@globalmagicko.com)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
magick_mind/__init__.py,sha256=fz_qJ7sdA12ve_pD2ARooKa6Prr4fi8YSRoLDcOsfZA,846
|
|
2
|
+
magick_mind/client.py,sha256=onfrxVP57McbZ5liJnHKNtDUIrDwqhikZxEJeBkN-3c,5980
|
|
3
|
+
magick_mind/config.py,sha256=qpDvHpiySxdpNK_IMYphFgo5CIDHVmrbFksVN_MW5r8,734
|
|
4
|
+
magick_mind/exceptions.py,sha256=V2-sG12wFSWCEgL09_6fNeNRYGd3YaiPx3CzwHewwXY,3357
|
|
5
|
+
magick_mind/routes.py,sha256=0_qQFe5U0z28EL26HpugtzTYJ0hfz-OP6Da-ZTDIWwk,2129
|
|
6
|
+
magick_mind/auth/__init__.py,sha256=KFVQgzRKOFQMet4xuWRDoz3olOxT2cBPGaHergrvBpk,219
|
|
7
|
+
magick_mind/auth/base.py,sha256=hOv7pIkGJWIyTTNiETi9tZUeSJNVgeaaWbKGpCwmIdg,1069
|
|
8
|
+
magick_mind/auth/email_password.py,sha256=Hp7PsyLTBzJ0DsVCq22TBwLZfpjGHO0LuZ7RRp6NugU,10084
|
|
9
|
+
magick_mind/http/__init__.py,sha256=_1xtQBZQ9JX-T3Bqauwr57ujHbW5xrXjnmWdAZ5UG44,120
|
|
10
|
+
magick_mind/http/client.py,sha256=-TIPzYclS8OZbUWxFPW5epli870z7I9shahq_hJN4Fw,10072
|
|
11
|
+
magick_mind/models/__init__.py,sha256=zXmYoh8-LC10d7sWcWBC2DtBGvP3_dy7Z64NDqwyBvE,393
|
|
12
|
+
magick_mind/models/auth.py,sha256=O23zq-mWRIHVznxkUmSoGQjUSAecdF7wpUbQ8ITESCk,618
|
|
13
|
+
magick_mind/models/common.py,sha256=BGnziCXSimYNvfB9rtkhhK4xjKkqeWuCq2vmo9o1LaA,940
|
|
14
|
+
magick_mind/models/errors.py,sha256=CL31vPvULvv_Jc1p0PMIAizGIw7zP9NozoK-bMic1l0,2312
|
|
15
|
+
magick_mind/models/v1/__init__.py,sha256=HH19PeDY1TRDPYMz_qQjQ3ngCdqKBlylY9CXdaU_VeM,2064
|
|
16
|
+
magick_mind/models/v1/api_keys.py,sha256=31n8HZc1VDd2esnO4r-1LNY2WGod6oyk8Qqe2xvx2rs,4015
|
|
17
|
+
magick_mind/models/v1/artifact.py,sha256=dE1O6H2bDaGRz_nTDZw8ssBlzPDXZCuVMrKLO6wKzAE,6040
|
|
18
|
+
magick_mind/models/v1/chat.py,sha256=UuGs66LBeVh_Vpdga0XX72Wsx42MS7YuuX1VK-CC0aI,3408
|
|
19
|
+
magick_mind/models/v1/corpus.py,sha256=71YhJd173b2XuPAD9Av3KNXWsuGHFyjB8oOd3n4bRRE,2522
|
|
20
|
+
magick_mind/models/v1/end_user.py,sha256=PmRn5Frhg-QZnhH5--eqgivk8uzskk5Cdea1pIZm7UE,2379
|
|
21
|
+
magick_mind/models/v1/history.py,sha256=Z32rCzSIpyoBUN1siYPfoLyR5Di__1uZoZQAuFmqeJE,2831
|
|
22
|
+
magick_mind/models/v1/mindspace.py,sha256=Hw-zjUif36a4RAhZZxXfHdjUHa9qGd0jBDf5U4fp_yk,4101
|
|
23
|
+
magick_mind/models/v1/model.py,sha256=7lBcyxwupGVkmeJ_5qWdMi4n8cTMMOtoSiIIXBcXkR4,876
|
|
24
|
+
magick_mind/models/v1/project.py,sha256=J0MhVOjqnGXA8waC1tTaZ2JzVqin_cHP_n1GSK3Qiuw,2215
|
|
25
|
+
magick_mind/realtime/__init__.py,sha256=AXxK__ZqHX0iaCQnkPsmpmuTkWQnqBm8JAx8gAUbjoQ,132
|
|
26
|
+
magick_mind/realtime/client.py,sha256=RoUW65df2y28V6T3klBIqrAtrWKI8xq8dqo9pDzT2JY,6817
|
|
27
|
+
magick_mind/realtime/handler.py,sha256=ovq35YrKHyAGrEFdGBSqvEpP4JfCAiXzDmXyPyXMAuU,3932
|
|
28
|
+
magick_mind/resources/README.md,sha256=idxTiaQWJW1o3hC6WBIoeTlX6nDr4AsqzE6ELppJuy8,5712
|
|
29
|
+
magick_mind/resources/__init__.py,sha256=6JUxgJQFUFvzMLADCPp1kQV9UJBT87z8oXnxkgBsrvc,1609
|
|
30
|
+
magick_mind/resources/base.py,sha256=UYyddfgGFbdv9m8dljBNeKOIbj1zT1h9L8kQKrJ43Fg,850
|
|
31
|
+
magick_mind/resources/v1/__init__.py,sha256=YloUAmuSFWH26cyv5y-QFdqeHYNTKuXsG_oNwrxh4EY,655
|
|
32
|
+
magick_mind/resources/v1/api_keys.py,sha256=AfVA9DFCnmen7Py-g5KOo1ILNuxbBY8ZX8WM9ll_liw,5078
|
|
33
|
+
magick_mind/resources/v1/artifact.py,sha256=XZ-vEPGilG88xZUjkPApa2fXfGDiSfs_Z3KDPfcVAz4,9145
|
|
34
|
+
magick_mind/resources/v1/chat.py,sha256=L38T85eypvosau4zZU3s4_fXcB4wdwGAjnO3f7ZOApM,4030
|
|
35
|
+
magick_mind/resources/v1/corpus.py,sha256=bn3bwh2eUbswksFX5-3uX6gOBOmfn5FrtcREo9SqouQ,3732
|
|
36
|
+
magick_mind/resources/v1/end_user.py,sha256=26IVghTh-1ChLICU_ymEE8RBeGNyWFnY0H_qUSUiwnk,5259
|
|
37
|
+
magick_mind/resources/v1/history.py,sha256=LYMZshDRxrOnMeIOKfikHxyetVQta-LIfEcCmxky-Hw,2791
|
|
38
|
+
magick_mind/resources/v1/mindspace.py,sha256=NiGsu-Rei9pXrxHN_Gp3-AkoVK2W4zwjja1H2inn2cg,10358
|
|
39
|
+
magick_mind/resources/v1/model.py,sha256=b7sIfm8uciE3C6rjWWaLJltgmdbfgIWB09Kra3gzCoY,549
|
|
40
|
+
magick_mind/resources/v1/project.py,sha256=kYcGMYyrjxj_nOcmt0ldNXneNct47CfJrFD25EhB6-g,4522
|
|
41
|
+
magickmind-0.1.1.dist-info/METADATA,sha256=XWjHK_hEnH6Wx6V90N5BIMLsaCDWaDu2Q9m-SCf-h-w,18864
|
|
42
|
+
magickmind-0.1.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
43
|
+
magickmind-0.1.1.dist-info/RECORD,,
|