magickmind 0.1.1__tar.gz

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 (59) hide show
  1. magickmind-0.1.1/.env.example +4 -0
  2. magickmind-0.1.1/.github/workflows/ci.yml +87 -0
  3. magickmind-0.1.1/.gitignore +26 -0
  4. magickmind-0.1.1/.gitrepo +12 -0
  5. magickmind-0.1.1/.python-version +1 -0
  6. magickmind-0.1.1/AGENTS.md +270 -0
  7. magickmind-0.1.1/CHANGELOG.md +19 -0
  8. magickmind-0.1.1/CONTRIBUTING.md +74 -0
  9. magickmind-0.1.1/GETTING_STARTED.md +111 -0
  10. magickmind-0.1.1/PKG-INFO +593 -0
  11. magickmind-0.1.1/README.md +559 -0
  12. magickmind-0.1.1/back_uppyproject.toml +58 -0
  13. magickmind-0.1.1/magick_mind/__init__.py +39 -0
  14. magickmind-0.1.1/magick_mind/auth/__init__.py +9 -0
  15. magickmind-0.1.1/magick_mind/auth/base.py +46 -0
  16. magickmind-0.1.1/magick_mind/auth/email_password.py +268 -0
  17. magickmind-0.1.1/magick_mind/client.py +188 -0
  18. magickmind-0.1.1/magick_mind/config.py +28 -0
  19. magickmind-0.1.1/magick_mind/exceptions.py +107 -0
  20. magickmind-0.1.1/magick_mind/http/__init__.py +5 -0
  21. magickmind-0.1.1/magick_mind/http/client.py +313 -0
  22. magickmind-0.1.1/magick_mind/models/__init__.py +17 -0
  23. magickmind-0.1.1/magick_mind/models/auth.py +30 -0
  24. magickmind-0.1.1/magick_mind/models/common.py +32 -0
  25. magickmind-0.1.1/magick_mind/models/errors.py +73 -0
  26. magickmind-0.1.1/magick_mind/models/v1/__init__.py +83 -0
  27. magickmind-0.1.1/magick_mind/models/v1/api_keys.py +115 -0
  28. magickmind-0.1.1/magick_mind/models/v1/artifact.py +151 -0
  29. magickmind-0.1.1/magick_mind/models/v1/chat.py +104 -0
  30. magickmind-0.1.1/magick_mind/models/v1/corpus.py +82 -0
  31. magickmind-0.1.1/magick_mind/models/v1/end_user.py +75 -0
  32. magickmind-0.1.1/magick_mind/models/v1/history.py +94 -0
  33. magickmind-0.1.1/magick_mind/models/v1/mindspace.py +130 -0
  34. magickmind-0.1.1/magick_mind/models/v1/model.py +25 -0
  35. magickmind-0.1.1/magick_mind/models/v1/project.py +73 -0
  36. magickmind-0.1.1/magick_mind/realtime/__init__.py +5 -0
  37. magickmind-0.1.1/magick_mind/realtime/client.py +202 -0
  38. magickmind-0.1.1/magick_mind/realtime/handler.py +122 -0
  39. magickmind-0.1.1/magick_mind/resources/README.md +201 -0
  40. magickmind-0.1.1/magick_mind/resources/__init__.py +42 -0
  41. magickmind-0.1.1/magick_mind/resources/base.py +31 -0
  42. magickmind-0.1.1/magick_mind/resources/v1/__init__.py +19 -0
  43. magickmind-0.1.1/magick_mind/resources/v1/api_keys.py +181 -0
  44. magickmind-0.1.1/magick_mind/resources/v1/artifact.py +287 -0
  45. magickmind-0.1.1/magick_mind/resources/v1/chat.py +120 -0
  46. magickmind-0.1.1/magick_mind/resources/v1/corpus.py +156 -0
  47. magickmind-0.1.1/magick_mind/resources/v1/end_user.py +181 -0
  48. magickmind-0.1.1/magick_mind/resources/v1/history.py +88 -0
  49. magickmind-0.1.1/magick_mind/resources/v1/mindspace.py +331 -0
  50. magickmind-0.1.1/magick_mind/resources/v1/model.py +19 -0
  51. magickmind-0.1.1/magick_mind/resources/v1/project.py +155 -0
  52. magickmind-0.1.1/magick_mind/routes.py +76 -0
  53. magickmind-0.1.1/main.py +6 -0
  54. magickmind-0.1.1/pyproject.toml +70 -0
  55. magickmind-0.1.1/specs/openapi.dev.json +4084 -0
  56. magickmind-0.1.1/specs/openapi.main.json +4084 -0
  57. magickmind-0.1.1/specs/openapi.new.json +1909 -0
  58. magickmind-0.1.1/specs/openapi.parsed.json +1873 -0
  59. magickmind-0.1.1/uv.lock +1037 -0
@@ -0,0 +1,4 @@
1
+ BIFROST_BASE_URL=https://dev-bifrost.magickmind.ai
2
+ BIFROST_EMAIL="user@example.com"
3
+ BIFROST_PASSWORD="your_secure_password"
4
+ BIFROST_WS_ENDPOINT=wss://dev-centrifugo.magickmind.ai/connection/websocket
@@ -0,0 +1,87 @@
1
+ name: AGD Magick Mind CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Format and/or Lint with Ruff and Push Changes
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout code
15
+ uses: actions/checkout@v4
16
+ with:
17
+ # 'ref:' determines which branch, tag, or commit the action checks out.
18
+ # For pull request events, 'github.head_ref' contains the source branch of the PR.
19
+ # For push events, 'github.head_ref' is empty, so we fall back to 'github.ref',
20
+ # which contains the full ref (e.g., "refs/heads/main").
21
+ ref: ${{ github.head_ref || github.ref }}
22
+
23
+ - name: Install and Format with Ruff
24
+ uses: astral-sh/ruff-action@v3
25
+ with:
26
+ args: "format"
27
+ # args: "check --fix"
28
+ # - run: ruff format
29
+ - name: Check for modified files
30
+ id: git_status
31
+ run: echo "modified=$(if git diff-index --quiet HEAD --; then echo "false"; else echo "true"; fi)" >> $GITHUB_OUTPUT
32
+ # run: |
33
+ # if git diff-index --quiet HEAD; then
34
+ # echo "::set-output name=modified::true"
35
+ # else
36
+ # echo "::set-output name=modified::false"
37
+ # fi
38
+ # - name: Debug set-output state
39
+ # run: |
40
+ # echo steps.git_status.outputs.modified
41
+ # echo steps.git_status.outputs.modified == 'true'
42
+ # - name: Ensure branch is checked out
43
+ # run: |
44
+ # # Determine branch name based on event type
45
+ # if [ -n "${GITHUB_HEAD_REF}" ]; then
46
+ # # Pull Request event: use head ref (source branch)
47
+ # branch="${GITHUB_HEAD_REF}"
48
+ # echo "Detected a pull request. Using head ref: $branch"
49
+ # # Fetch the branch from the remote if it isn’t available locally.
50
+ # git fetch origin "${branch}:${branch}"
51
+ # elif [[ "${GITHUB_REF}" == refs/heads/* ]]; then
52
+ # # Push event: extract branch name from GITHUB_REF
53
+ # branch="${GITHUB_REF#refs/heads/}"
54
+ # echo "Detected a push event on branch: $branch"
55
+ # else
56
+ # echo "Not a branch event (likely a tag); skipping commit step."
57
+ # exit 0
58
+ # fi
59
+ # echo "Switching to branch: $branch"
60
+ # git switch $branch
61
+
62
+ - name: Push changes
63
+ if: steps.git_status.outputs.modified == 'true'
64
+ run: |
65
+ git config --global user.name "github-actions[bot]"
66
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
67
+ git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
68
+ git commit -am "CI Workflow: Style fixes by Ruff"
69
+ git push
70
+ # test:
71
+ # name: Run Tests
72
+ # runs-on: ubuntu-latest
73
+ # steps:
74
+ # - name: Checkout code
75
+ # uses: actions/checkout@v4
76
+ #
77
+ # - name: Set up Python
78
+ # uses: actions/setup-python@v4
79
+ # with:
80
+ # python-version: "3.x"
81
+ #
82
+ # - name: Install dependencies
83
+ # run: pip install -r requirements.txt
84
+ #
85
+ # - name: Run tests
86
+ # run: pytest
87
+
@@ -0,0 +1,26 @@
1
+ **/__pycache__/
2
+ .vscode/
3
+ *.tar
4
+ logs/
5
+ .idea/
6
+ tmp/
7
+
8
+ # StarUML temporary files
9
+ *.mdj.bak
10
+ *.mdj~
11
+ semantic_working_dir
12
+ *.log
13
+
14
+ # Environments
15
+ .env
16
+ .venv
17
+ env/
18
+ venv/
19
+ ENV/
20
+ env.bak/
21
+ venv.bak/
22
+
23
+ *.egg-info/
24
+
25
+ # Hypothesis Cache
26
+ .hypothesis/
@@ -0,0 +1,12 @@
1
+ ; DO NOT EDIT (unless you know what you are doing)
2
+ ;
3
+ ; This subdirectory is a git "subrepo", and this file is maintained by the
4
+ ; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
5
+ ;
6
+ [subrepo]
7
+ remote = git@github.com:General-Magick-Industries/AGD_Magick_Mind_SDK.git
8
+ branch = main
9
+ commit = 93b35d17bc15bb09d080da87d028101f23fe2ee8
10
+ parent = 34e5948f872404c27c1278d8c3ddb2116302a61c
11
+ method = rebase
12
+ cmdver = 0.4.9
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,270 @@
1
+ # SDK - Official MagickMind Python Client
2
+
3
+ > Python SDK for the Bifrost API gateway. For **service users** (backends/bots) to authenticate and interact with MagickMind on behalf of their end users.
4
+
5
+ **Python runtime required** - Uses `httpx` and `centrifuge-python`. Runs in Python backends, CLI, scripts, desktop apps.
6
+
7
+ ## Architecture: Service Users vs End Users
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────────┐
11
+ │ YOUR SYSTEM │
12
+ │ ┌──────────────┐ ┌──────────────────────────────────────┐ │
13
+ │ │ Your End │────▶│ Your Backend (Service User) │ │
14
+ │ │ Users │ │ - Authenticates with Bifrost (JWT) │ │
15
+ │ │ (own auth) │◀────│ - Manages end users via end-user svc│ │
16
+ │ └──────────────┘ │ - Calls Bifrost with sender_id param│ │
17
+ │ └──────────────────────────────────────┘ │
18
+ └─────────────────────────────────────────────────────────────────┘
19
+
20
+ ▼ SDK / REST
21
+ ┌─────────────────────────────────────────────────────────────────┐
22
+ │ MAGICKMIND │
23
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
24
+ │ │ Bifrost │──│ Xavier │──│ Cortex │──│ Centrifugo │ │
25
+ │ │ (gateway)│ │ (chat) │ │ (AI) │ │ (streaming) │ │
26
+ │ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │
27
+ └─────────────────────────────────────────────────────────────────┘
28
+ ```
29
+
30
+ **Key concepts:**
31
+ - **Service User**: Your backend/bot that authenticates with Bifrost via JWT (email/password login)
32
+ - **End User**: YOUR users, managed by YOU. Created via `end-user` gRPC service. No direct Bifrost auth.
33
+ - **sender_id/user_id**: End user identifier passed in API calls (e.g., chat requests)
34
+
35
+ **Centrifugo channel format:** `personal:{end_user_id}#{service_account_id}`
36
+ - Service subscribes to channels for its end users
37
+ - Streams responses back to end users via YOUR transport (WebSocket, Telegram, etc.)
38
+
39
+ ## Purpose & Responsibilities
40
+
41
+ - **Authentication**: Service user email/password → JWT with auto-refresh
42
+ - **HTTP Client**: Authenticated requests to Bifrost REST API
43
+ - **Typed Resources**: v1/chat, mindspace, artifact, end-user, etc. with Pydantic models
44
+ - **Real-time**: Centrifugo pub/sub for streaming responses to relay to your end users
45
+ - **End User Management**: Create/query/update end users scoped to your service account
46
+
47
+ ## Key Files & Entry Points
48
+
49
+ | Need | Look Here |
50
+ |------|-----------|
51
+ | Main client | `magick_mind/client.py` - `MagickMind` class |
52
+ | HTTP client | `magick_mind/http/client.py` - authenticated requests |
53
+ | Real-time | `magick_mind/realtime/client.py` - Centrifugo subscriptions |
54
+ | Auth provider | `magick_mind/auth/email_password.py` - JWT login/refresh |
55
+ | Chat resource | `magick_mind/resources/v1/chat.py` |
56
+ | Mindspace resource | `magick_mind/resources/v1/mindspace.py` |
57
+ | Artifact resource | `magick_mind/resources/v1/artifact.py` |
58
+ | Request/Response models | `magick_mind/models/v1/` |
59
+ | Exceptions | `magick_mind/exceptions.py` |
60
+ | Examples | `examples/` - usage patterns |
61
+
62
+ ## Quick Start
63
+
64
+ ```python
65
+ from magick_mind import MagickMind
66
+
67
+ # Initialize client as SERVICE USER (your backend)
68
+ client = MagickMind(
69
+ email="myservice@example.com", # Your service account
70
+ password="secret",
71
+ base_url="https://bifrost.magickmind.io"
72
+ )
73
+
74
+ # Create/get an end user (YOUR user, e.g., from your auth system)
75
+ end_user = await client.v1.end_user.create_or_get(
76
+ external_id="your-user-123", # Your user ID
77
+ metadata={"name": "Alice"}
78
+ )
79
+
80
+ # Send chat message ON BEHALF OF your end user
81
+ response = await client.v1.chat.send(
82
+ mindspace_id="ms-123",
83
+ sender_id=end_user.id, # End user ID
84
+ message="Hello, world!"
85
+ )
86
+
87
+ # Subscribe to Centrifugo for this end user's responses
88
+ class MyHandler:
89
+ async def on_message(self, user_id: str, payload: dict):
90
+ # Relay this to YOUR end user via your transport
91
+ print(f"Response for {user_id}: {payload}")
92
+
93
+ await client.realtime.connect(events=MyHandler())
94
+ await client.realtime.subscribe(end_user.id) # Subscribe for this end user
95
+ ```
96
+
97
+ ## Service-Specific Patterns
98
+
99
+ ### Authentication (Auto-Refresh)
100
+ ```python
101
+ # magick_mind/auth/email_password.py
102
+ # JWT refreshed automatically (expires_in - 10s buffer)
103
+ client = MagickMind(email="...", password="...")
104
+ # Token injected into all requests automatically
105
+
106
+ # Check auth status
107
+ if client.is_authenticated():
108
+ ...
109
+ ```
110
+
111
+ ### HTTP Requests
112
+ ```python
113
+ # Low-level (magick_mind/http/client.py)
114
+ response = await client.http.request("GET", "/v1/chat/messages")
115
+
116
+ # High-level via resources
117
+ messages = await client.v1.mindspace.get_messages(
118
+ mindspace_id="ms-123",
119
+ after_id="msg-456" # For pagination/sync
120
+ )
121
+ ```
122
+
123
+ ### Real-time Subscriptions
124
+ ```python
125
+ # magick_mind/realtime/client.py
126
+ # Channel format: personal:{end_user_id}#{service_account_id}
127
+ # Service subscribes to channels for its end users
128
+
129
+ class EventHandler:
130
+ async def on_message(self, end_user_id: str, payload: dict):
131
+ # Relay to YOUR end user via your transport (WebSocket, Telegram, etc.)
132
+ your_websocket.send(end_user_id, payload)
133
+
134
+ async def on_error(self, error: Exception):
135
+ # Handle connection error
136
+ pass
137
+
138
+ await client.realtime.connect(events=EventHandler())
139
+ await client.realtime.subscribe(end_user_id="your-end-user-123")
140
+ ```
141
+
142
+ ### History Sync Pattern
143
+ ```python
144
+ # Get messages since last known, then subscribe for real-time
145
+ last_known_id = get_last_message_id_from_db()
146
+ messages = await client.v1.mindspace.get_messages(
147
+ mindspace_id="ms-123",
148
+ after_id=last_known_id
149
+ )
150
+ save_to_db(messages)
151
+
152
+ # Now subscribe for new messages for this end user
153
+ await client.realtime.subscribe(end_user_id="your-end-user-123")
154
+ ```
155
+
156
+ ### Error Handling
157
+ ```python
158
+ from magick_mind.exceptions import (
159
+ MagickMindError, # Base exception
160
+ AuthenticationError, # Login failed
161
+ TokenExpiredError, # Token refresh failed
162
+ APIError, # API returned error
163
+ RateLimitError, # Rate limited
164
+ )
165
+
166
+ try:
167
+ await client.v1.chat.send(...)
168
+ except AuthenticationError:
169
+ # Re-authenticate
170
+ except APIError as e:
171
+ print(f"API error: {e.message}, status: {e.status_code}")
172
+ ```
173
+
174
+ ## Testing
175
+
176
+ ```bash
177
+ # Run all tests
178
+ uv run pytest
179
+
180
+ # With coverage
181
+ uv run pytest --cov=magick_mind
182
+ ```
183
+
184
+ **Test structure**:
185
+ ```
186
+ tests/
187
+ ├── conftest.py # Fixtures: mock_auth, test_client, schema_registry
188
+ ├── test_auth.py # Auth provider tests
189
+ ├── test_resources/ # Resource client tests
190
+ ├── test_realtime/ # Real-time subscription tests
191
+ └── contract/ # OpenAPI contract validation
192
+ ├── openapi.json # API schema
193
+ └── test_contracts.py # Payload validation
194
+ ```
195
+
196
+ **Fixtures** (`conftest.py`):
197
+ - `mock_client` - httpx.MockTransport for HTTP mocking
198
+ - `authenticated_client` - Pre-authenticated MagickMind instance
199
+ - `mock_auth` - Mocked auth provider
200
+ - `schema_registry` - OpenAPI schema validation
201
+
202
+ **Mocking patterns**:
203
+ ```python
204
+ # Mock auth
205
+ @patch("magick_mind.auth.email_password._login")
206
+ def test_auth(mock_login):
207
+ mock_login.return_value = {"access_token": "...", "expires_in": 3600}
208
+ ...
209
+
210
+ # Mock HTTP with pytest-httpx
211
+ def test_chat(httpx_mock):
212
+ httpx_mock.add_response(json={"message_id": "123"})
213
+ ...
214
+ ```
215
+
216
+ ## Configuration
217
+
218
+ ```python
219
+ from magick_mind import MagickMind
220
+
221
+ client = MagickMind(
222
+ email="service@example.com",
223
+ password="secret",
224
+ base_url="https://bifrost.magickmind.io", # Or from BIFROST_BASE_URL env
225
+ )
226
+ ```
227
+
228
+ **Environment variables**:
229
+ ```bash
230
+ BIFROST_BASE_URL=https://bifrost.magickmind.io
231
+ # Credentials typically passed directly, not via env
232
+ ```
233
+
234
+ ## Dependencies
235
+
236
+ Key packages from `pyproject.toml`:
237
+ - `httpx>=0.27` - HTTP client
238
+ - `pydantic>=2.0` - Models and validation
239
+ - `centrifuge>=0.9` - Real-time WebSocket
240
+ - `pydantic-settings` - Configuration
241
+
242
+ **Dev dependencies**:
243
+ - `pytest`, `pytest-httpx`, `pytest-asyncio` - Testing
244
+
245
+ ## Common Commands
246
+
247
+ ```bash
248
+ # Install dependencies
249
+ uv sync
250
+
251
+ # Run tests
252
+ uv run pytest -v
253
+
254
+ # Type check
255
+ uv run pyright
256
+
257
+ # Format
258
+ uv run ruff format .
259
+ ```
260
+
261
+ ## Gotchas
262
+
263
+ 1. **Service users only** - This SDK authenticates service accounts (backends/bots), not end users. End users are managed via `end-user` service and passed as `sender_id`/`user_id` params.
264
+ 2. **Python only** - Uses httpx/centrifuge-python; for other languages, use Bifrost REST directly
265
+ 3. **Async preferred** - Most methods are async; use `asyncio.to_thread` for sync contexts
266
+ 4. **Auto-refresh timing** - Token refreshes 10s before expiry; long-running ops may still fail
267
+ 5. **Real-time before REST** - For chat, subscribe to channel BEFORE sending message to catch response
268
+ 6. **Contract tests** - Tests validate against `tests/contract/openapi.json`; update if API changes
269
+ 7. **Channel format** - `personal:{end_user_id}#{service_account_id}` - service subscribes for its end users
270
+ 8. **No direct frontend access** - End users don't call Bifrost directly; your backend relays via this SDK
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.0.1] - 2026-01-20
9
+
10
+ ### Added
11
+ - **Realtime WebSocket Client**: Full support for real-time interaction in `magick_mind.realtime`.
12
+ - **Resources**:
13
+ - `Chat` and `History` resources for messaging.
14
+ - `Mindspace`, `Project`, `EndUser`, `Corpus` resources for management.
15
+ - **Artifacts**: Support for file uploads and attachment handling.
16
+ - **Examples**:
17
+ - Detailed `setup_resources.py` script.
18
+ - Complete examples for Realtime Chat and Backend integration.
19
+
@@ -0,0 +1,74 @@
1
+ # Contributing to Magick Mind SDK
2
+
3
+ ## Development Setup
4
+
5
+ ```bash
6
+ # Clone and install
7
+ git clone <repo>
8
+ cd AGD_Magick_Mind_SDK
9
+ uv sync
10
+ ```
11
+
12
+ ## Running Tests
13
+
14
+ ```bash
15
+ # All tests
16
+ uv run pytest
17
+
18
+ # Contract tests only
19
+ uv run pytest -m contract -v
20
+
21
+ # Unit tests
22
+ uv run pytest tests/unit/ -v
23
+ ```
24
+
25
+ ## Contract Testing Workflow
26
+
27
+ We use serialization-based contract testing to ensure SDK models match the bifrost API.
28
+
29
+ ### How It Works
30
+
31
+ 1. **Spec snapshots** in `specs/` represent the API contract
32
+ 2. **Tests** validate that SDK payloads match the spec
33
+ 3. **Serializers** transform optional SDK fields to API-required defaults
34
+
35
+ ### Updating Specs
36
+
37
+ When bifrost API changes:
38
+
39
+ ```bash
40
+ # 1. Generate new spec in bifrost
41
+ cd ../bifrost
42
+ goctl api plugin -p goctl-openapi -api api/v1/*.api -dir .
43
+
44
+ # 2. Copy to SDK (dev or main depending on branch)
45
+ cp api/openapi.json ../AGD_Magick_Mind_SDK/specs/openapi.dev.json
46
+
47
+ # 3. Run contract tests
48
+ cd ../AGD_Magick_Mind_SDK
49
+ uv run pytest -m contract -v
50
+
51
+ # 4. Fix any failures by updating SDK models
52
+ ```
53
+
54
+ ### Adding New Models
55
+
56
+ 1. Add model to `tests/contract/test_payloads.py` → `MODEL_REGISTRY`
57
+ 2. Add instance creation in `create_minimal_instance()`
58
+ 3. Add `@field_serializer` for optional fields if needed
59
+
60
+ See `tests/contract/README.md` for detailed instructions.
61
+
62
+ ## Code Style
63
+
64
+ - Format: `uv run ruff format .`
65
+ - Lint: `uv run ruff check .`
66
+ - Type check: `uv run pyright`
67
+
68
+ ## Pull Request Process
69
+
70
+ 1. Create feature branch
71
+ 2. Make changes
72
+ 3. Run tests: `uv run pytest`
73
+ 4. Run contract tests: `uv run pytest -m contract`
74
+ 5. Submit PR
@@ -0,0 +1,111 @@
1
+ # Getting Started with Magick Mind SDK
2
+
3
+ A 10-minute guide to running your first examples.
4
+
5
+ ## Prerequisites
6
+
7
+ - Python 3.8+
8
+ - Access to a Bifrost instance
9
+ - Service credentials (email/password)
10
+
11
+ ## Step 1: Install SDK
12
+
13
+ ```bash
14
+ cd AGD_Magick_Mind_SDK
15
+ pip install -e .
16
+ ```
17
+
18
+ ## Step 2: Set Environment Variables
19
+
20
+ **Option A: Using .env file** (Easier, persists across sessions)
21
+
22
+ 1. Copy `test.env` to `.env`:
23
+ ```bash
24
+ cp test.env .env
25
+ ```
26
+
27
+ 2. Edit `.env` with your credentials
28
+ 3. Run examples using the helper script:
29
+ ```bash
30
+ python run_example.py examples/chat_example.py
31
+ ```
32
+
33
+ The helper script loads `.env` automatically (no extra dependencies needed).
34
+
35
+ **Alternative: Source manually (Bash/zsh only)**
36
+
37
+ ```bash
38
+ set -a; source .env; set +a
39
+ python examples/chat_example.py
40
+ ```
41
+
42
+ **Option B: Export manually** (Quick for testing)
43
+
44
+ ```bash
45
+ # Bash/zsh
46
+ export BIFROST_BASE_URL="http://localhost:8888"
47
+ export BIFROST_EMAIL="service@example.com"
48
+ export BIFROST_PASSWORD="your-password"
49
+
50
+ # Fish
51
+ set -gx BIFROST_BASE_URL "http://localhost:8888"
52
+ set -gx BIFROST_EMAIL "service@example.com"
53
+ set -gx BIFROST_PASSWORD "your-password"
54
+
55
+ python examples/chat_example.py
56
+ ```
57
+
58
+ ## Step 3: Try Examples (In Order)
59
+
60
+ ### 1. Authentication (30 seconds)
61
+ ```bash
62
+ python examples/email_password_auth.py
63
+ ```
64
+ **What it does:** Connects to Bifrost and authenticates.
65
+
66
+ ### 2. Chat Message (1 minute)
67
+ ```bash
68
+ python examples/chat_example.py
69
+ ```
70
+ **What it does:** Sends a message to an AI mindspace.
71
+
72
+ ### 3. Message History (1 minute)
73
+ ```bash
74
+ python examples/history_example.py
75
+ ```
76
+ **What it does:** Fetches past messages with pagination.
77
+
78
+ ### 4. Realtime Messages (2 minutes)
79
+ ```bash
80
+ python examples/realtime_chat.py
81
+ ```
82
+ **What it does:** Listens for AI responses in real-time.
83
+
84
+ ### 5. Complete Workflow (5 minutes)
85
+ ```bash
86
+ python examples/complete_chat_workflow.py
87
+ ```
88
+ **What it does:** Full loop - send via HTTP, receive via realtime.
89
+
90
+ ## What's Next?
91
+
92
+ **Explore by Category:**
93
+ - **CRUD**: `mindspace_example.py`, `project_example.py`, `corpus_example.py`
94
+ - **Backend Patterns**: `caching_example.py`, `notification_pattern_example.py`
95
+ - **Production**: `backend_service.py`, `fan_out_relay.py`
96
+
97
+ **Read Documentation:**
98
+ - [Backend Architecture](docs/architecture/backend_architecture.md)
99
+ - [Event-Driven Patterns](docs/architecture/event_driven_patterns.md)
100
+ - [Realtime Guide](docs/realtime_guide.md)
101
+
102
+ ## Troubleshooting
103
+
104
+ **"Connection refused"**
105
+ → Start Bifrost: `docker-compose up bifrost`
106
+
107
+ **"Invalid credentials"**
108
+ → Check `BIFROST_EMAIL` and `BIFROST_PASSWORD` in your environment
109
+
110
+ **"Module not found"**
111
+ → Run `pip install -e .` from SDK root directory