ensoul 0.1.0__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 (49) hide show
  1. ensoul-0.1.0/.gitignore +39 -0
  2. ensoul-0.1.0/PKG-INFO +215 -0
  3. ensoul-0.1.0/README.md +188 -0
  4. ensoul-0.1.0/examples/quickstart.py +75 -0
  5. ensoul-0.1.0/pyproject.toml +55 -0
  6. ensoul-0.1.0/src/ensoul/__init__.py +60 -0
  7. ensoul-0.1.0/src/ensoul/_types.py +29 -0
  8. ensoul-0.1.0/src/ensoul/auth.py +67 -0
  9. ensoul-0.1.0/src/ensoul/client.py +182 -0
  10. ensoul-0.1.0/src/ensoul/config.py +33 -0
  11. ensoul-0.1.0/src/ensoul/errors.py +189 -0
  12. ensoul-0.1.0/src/ensoul/generated/aggregate.py +47 -0
  13. ensoul-0.1.0/src/ensoul/generated/auth.py +56 -0
  14. ensoul-0.1.0/src/ensoul/generated/chat.py +76 -0
  15. ensoul-0.1.0/src/ensoul/generated/domains.py +69 -0
  16. ensoul-0.1.0/src/ensoul/generated/endpoints.py +2106 -0
  17. ensoul-0.1.0/src/ensoul/generated/enums.py +82 -0
  18. ensoul-0.1.0/src/ensoul/generated/personas.py +112 -0
  19. ensoul-0.1.0/src/ensoul/generated/sessions.py +54 -0
  20. ensoul-0.1.0/src/ensoul/generated/simulations.py +98 -0
  21. ensoul-0.1.0/src/ensoul/http.py +349 -0
  22. ensoul-0.1.0/src/ensoul/pagination.py +163 -0
  23. ensoul-0.1.0/src/ensoul/rate_limit.py +89 -0
  24. ensoul-0.1.0/src/ensoul/resources/__init__.py +40 -0
  25. ensoul-0.1.0/src/ensoul/resources/aggregate.py +204 -0
  26. ensoul-0.1.0/src/ensoul/resources/auth_resource.py +121 -0
  27. ensoul-0.1.0/src/ensoul/resources/chat.py +203 -0
  28. ensoul-0.1.0/src/ensoul/resources/domains.py +126 -0
  29. ensoul-0.1.0/src/ensoul/resources/frameworks.py +144 -0
  30. ensoul-0.1.0/src/ensoul/resources/health.py +59 -0
  31. ensoul-0.1.0/src/ensoul/resources/info.py +67 -0
  32. ensoul-0.1.0/src/ensoul/resources/memory.py +182 -0
  33. ensoul-0.1.0/src/ensoul/resources/personas.py +237 -0
  34. ensoul-0.1.0/src/ensoul/resources/sessions.py +176 -0
  35. ensoul-0.1.0/src/ensoul/resources/simulations.py +261 -0
  36. ensoul-0.1.0/src/ensoul/streaming.py +250 -0
  37. ensoul-0.1.0/tests/.gitkeep +0 -0
  38. ensoul-0.1.0/tests/__init__.py +0 -0
  39. ensoul-0.1.0/tests/conftest.py +51 -0
  40. ensoul-0.1.0/tests/test_chat.py +143 -0
  41. ensoul-0.1.0/tests/test_client.py +126 -0
  42. ensoul-0.1.0/tests/test_config.py +54 -0
  43. ensoul-0.1.0/tests/test_conformance.py +430 -0
  44. ensoul-0.1.0/tests/test_errors.py +189 -0
  45. ensoul-0.1.0/tests/test_integration.py +305 -0
  46. ensoul-0.1.0/tests/test_pagination.py +159 -0
  47. ensoul-0.1.0/tests/test_personas.py +218 -0
  48. ensoul-0.1.0/tests/test_streaming.py +214 -0
  49. ensoul-0.1.0/uv.lock +484 -0
@@ -0,0 +1,39 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ .venv/
7
+ *.egg
8
+
9
+ # TypeScript / Node
10
+ node_modules/
11
+ dist/
12
+ *.tsbuildinfo
13
+
14
+ # Swift
15
+ .build/
16
+ .swiftpm/
17
+ Package.resolved
18
+
19
+ # Unity
20
+ Library/
21
+ Temp/
22
+ obj/
23
+ Logs/
24
+
25
+ # C++
26
+ build/
27
+ cmake-build-*/
28
+ *.o
29
+ *.a
30
+
31
+ # Kotlin
32
+ .gradle/
33
+ build/
34
+ *.class
35
+
36
+ # General
37
+ .DS_Store
38
+ *.swp
39
+ *.swo
ensoul-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,215 @@
1
+ Metadata-Version: 2.4
2
+ Name: ensoul
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for the Ensoul API
5
+ Project-URL: Homepage, https://ensoul-ai.com
6
+ Project-URL: Documentation, https://ensoul-ai.com/products/studio/docs
7
+ Project-URL: Repository, https://github.com/ensoul-ai/ensoul-sdk
8
+ Project-URL: Issues, https://github.com/ensoul-ai/ensoul-sdk/issues
9
+ Author-email: Ensoul <support@ensoul.ai>
10
+ License-Expression: Apache-2.0
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Typing :: Typed
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: httpx>=0.25.0
19
+ Requires-Dist: pydantic>=2.0.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: mypy; extra == 'dev'
22
+ Requires-Dist: pytest; extra == 'dev'
23
+ Requires-Dist: pytest-asyncio; extra == 'dev'
24
+ Requires-Dist: respx; extra == 'dev'
25
+ Requires-Dist: ruff; extra == 'dev'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # Ensoul Python SDK
29
+
30
+ Python client library for the Ensoul personality simulation API.
31
+
32
+ ## Installation
33
+
34
+ ```
35
+ pip install ensoul
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ ```python
41
+ from ensoul import Ensoul
42
+
43
+ client = Ensoul(api_key="your-api-key")
44
+
45
+ # Create a persona
46
+ persona = client.personas.create(name="Alex", domain="my_domain")
47
+
48
+ # Send a chat message
49
+ response = client.chat.send(persona.id, "Hello, who are you?")
50
+ print(response.response)
51
+ ```
52
+
53
+ The API key can also be set via the `ENSOUL_API_KEY` environment variable, in which case no `api_key` argument is needed.
54
+
55
+ The client supports context managers for automatic cleanup:
56
+
57
+ ```python
58
+ with Ensoul(api_key="your-api-key") as client:
59
+ persona = client.personas.get("persona-id")
60
+ ```
61
+
62
+ ## Async Usage
63
+
64
+ ```python
65
+ import asyncio
66
+ from ensoul import AsyncEnsoul
67
+
68
+ async def main():
69
+ async with AsyncEnsoul(api_key="your-api-key") as client:
70
+ persona = await client.personas.create(name="Jordan", domain="my_domain")
71
+ response = await client.chat.send(persona.id, "Tell me about yourself.")
72
+ print(response.response)
73
+
74
+ asyncio.run(main())
75
+ ```
76
+
77
+ ## Streaming
78
+
79
+ Chat supports server-sent events (SSE) for streaming responses:
80
+
81
+ ```python
82
+ from ensoul import Ensoul
83
+ from ensoul.streaming import parse_chat_event
84
+
85
+ client = Ensoul(api_key="your-api-key")
86
+
87
+ stream = client.chat.stream("persona-id", "What do you think about music?")
88
+ for event in stream.events():
89
+ parsed = parse_chat_event(event)
90
+ if not parsed.is_final:
91
+ print(parsed.chunk, end="", flush=True)
92
+ else:
93
+ print() # newline after stream completes
94
+ ```
95
+
96
+ The async client returns an `AsyncSSEStream` that works the same way with `async for`.
97
+
98
+ ## Pagination
99
+
100
+ List endpoints return a `SyncPage` (or `AsyncPage`) object. Use `.auto_paging_iter()` to iterate through all pages automatically:
101
+
102
+ ```python
103
+ # Manual page access
104
+ page = client.personas.list(per_page=50)
105
+ print(page.items) # current page items
106
+ print(page.total) # total count across all pages
107
+
108
+ # Automatic pagination — fetches subsequent pages as needed
109
+ for persona in client.personas.list().auto_paging_iter():
110
+ print(persona.name)
111
+ ```
112
+
113
+ Async pagination works the same way with `async for`.
114
+
115
+ ## Error Handling
116
+
117
+ All SDK errors inherit from `EnsoulError`. HTTP errors are subclasses of `APIError`:
118
+
119
+ ```python
120
+ from ensoul.errors import (
121
+ EnsoulError,
122
+ APIError,
123
+ AuthenticationError,
124
+ AuthorizationError,
125
+ NotFoundError,
126
+ RateLimitError,
127
+ ValidationError,
128
+ ConflictError,
129
+ ServerError,
130
+ )
131
+
132
+ try:
133
+ persona = client.personas.get("nonexistent-id")
134
+ except NotFoundError:
135
+ print("Persona not found")
136
+ except AuthenticationError:
137
+ print("Invalid or missing API key")
138
+ except RateLimitError:
139
+ print("Rate limit exceeded — back off and retry")
140
+ except APIError as e:
141
+ print(f"API error {e.status_code}: {e.message}")
142
+ ```
143
+
144
+ ## Configuration
145
+
146
+ The client reads two environment variables as defaults:
147
+
148
+ | Variable | Purpose |
149
+ |----------|---------|
150
+ | `ENSOUL_API_KEY` | API key (avoids passing `api_key=` in code) |
151
+ | `ENSOUL_BASE_URL` | API base URL (default: `https://api.ensoul-ai.com`) |
152
+
153
+ **Demo API** — the current hosted demo is available at:
154
+
155
+ ```bash
156
+ export ENSOUL_BASE_URL="https://api.demo.ensoul-ai.com"
157
+ export ENSOUL_API_KEY="your-api-key"
158
+ ```
159
+
160
+ With these set, `Ensoul()` connects to the demo with no constructor arguments.
161
+
162
+ You can also pass the base URL explicitly:
163
+
164
+ ```python
165
+ client = Ensoul(api_key="ens_...", base_url="https://api.demo.ensoul-ai.com")
166
+ ```
167
+
168
+ ## Authentication
169
+
170
+ **API key** (recommended):
171
+
172
+ ```python
173
+ client = Ensoul(api_key="ens_...")
174
+ # or set ENSOUL_API_KEY in the environment
175
+ client = Ensoul()
176
+ ```
177
+
178
+ **Bearer token**:
179
+
180
+ ```python
181
+ client = Ensoul(bearer_token="eyJ...")
182
+ ```
183
+
184
+ **OAuth2 token exchange** (client credentials flow):
185
+
186
+ ```python
187
+ token_response = client.auth.token(
188
+ grant_type="client_credentials",
189
+ client_id="your-client-id",
190
+ client_secret="your-client-secret",
191
+ )
192
+ authed_client = Ensoul(bearer_token=token_response.access_token)
193
+ ```
194
+
195
+ ## Resources
196
+
197
+ | Namespace | Description |
198
+ |-----------|-------------|
199
+ | `client.personas` | CRUD, list (paginated), batch create, personality vectors, filters, connections |
200
+ | `client.chat` | Send messages, streaming SSE, conversation history |
201
+ | `client.domains` | Domain configuration management |
202
+ | `client.simulations` | Time-based evolution simulations |
203
+ | `client.aggregate` | Aggregate queries with streaming results |
204
+ | `client.memory` | Persona memory management |
205
+ | `client.sessions` | Hierarchical session orchestration |
206
+ | `client.frameworks` | Framework management |
207
+ | `client.auth` | OAuth2 token exchange and API key management |
208
+ | `client.health` | Service health checks |
209
+ | `client.info` | Server info and configuration |
210
+
211
+ ## Requirements
212
+
213
+ - Python 3.11+
214
+ - [`httpx`](https://www.python-httpx.org/) — HTTP transport
215
+ - [`pydantic`](https://docs.pydantic.dev/) 2.x — request and response models
ensoul-0.1.0/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # Ensoul Python SDK
2
+
3
+ Python client library for the Ensoul personality simulation API.
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ pip install ensoul
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from ensoul import Ensoul
15
+
16
+ client = Ensoul(api_key="your-api-key")
17
+
18
+ # Create a persona
19
+ persona = client.personas.create(name="Alex", domain="my_domain")
20
+
21
+ # Send a chat message
22
+ response = client.chat.send(persona.id, "Hello, who are you?")
23
+ print(response.response)
24
+ ```
25
+
26
+ The API key can also be set via the `ENSOUL_API_KEY` environment variable, in which case no `api_key` argument is needed.
27
+
28
+ The client supports context managers for automatic cleanup:
29
+
30
+ ```python
31
+ with Ensoul(api_key="your-api-key") as client:
32
+ persona = client.personas.get("persona-id")
33
+ ```
34
+
35
+ ## Async Usage
36
+
37
+ ```python
38
+ import asyncio
39
+ from ensoul import AsyncEnsoul
40
+
41
+ async def main():
42
+ async with AsyncEnsoul(api_key="your-api-key") as client:
43
+ persona = await client.personas.create(name="Jordan", domain="my_domain")
44
+ response = await client.chat.send(persona.id, "Tell me about yourself.")
45
+ print(response.response)
46
+
47
+ asyncio.run(main())
48
+ ```
49
+
50
+ ## Streaming
51
+
52
+ Chat supports server-sent events (SSE) for streaming responses:
53
+
54
+ ```python
55
+ from ensoul import Ensoul
56
+ from ensoul.streaming import parse_chat_event
57
+
58
+ client = Ensoul(api_key="your-api-key")
59
+
60
+ stream = client.chat.stream("persona-id", "What do you think about music?")
61
+ for event in stream.events():
62
+ parsed = parse_chat_event(event)
63
+ if not parsed.is_final:
64
+ print(parsed.chunk, end="", flush=True)
65
+ else:
66
+ print() # newline after stream completes
67
+ ```
68
+
69
+ The async client returns an `AsyncSSEStream` that works the same way with `async for`.
70
+
71
+ ## Pagination
72
+
73
+ List endpoints return a `SyncPage` (or `AsyncPage`) object. Use `.auto_paging_iter()` to iterate through all pages automatically:
74
+
75
+ ```python
76
+ # Manual page access
77
+ page = client.personas.list(per_page=50)
78
+ print(page.items) # current page items
79
+ print(page.total) # total count across all pages
80
+
81
+ # Automatic pagination — fetches subsequent pages as needed
82
+ for persona in client.personas.list().auto_paging_iter():
83
+ print(persona.name)
84
+ ```
85
+
86
+ Async pagination works the same way with `async for`.
87
+
88
+ ## Error Handling
89
+
90
+ All SDK errors inherit from `EnsoulError`. HTTP errors are subclasses of `APIError`:
91
+
92
+ ```python
93
+ from ensoul.errors import (
94
+ EnsoulError,
95
+ APIError,
96
+ AuthenticationError,
97
+ AuthorizationError,
98
+ NotFoundError,
99
+ RateLimitError,
100
+ ValidationError,
101
+ ConflictError,
102
+ ServerError,
103
+ )
104
+
105
+ try:
106
+ persona = client.personas.get("nonexistent-id")
107
+ except NotFoundError:
108
+ print("Persona not found")
109
+ except AuthenticationError:
110
+ print("Invalid or missing API key")
111
+ except RateLimitError:
112
+ print("Rate limit exceeded — back off and retry")
113
+ except APIError as e:
114
+ print(f"API error {e.status_code}: {e.message}")
115
+ ```
116
+
117
+ ## Configuration
118
+
119
+ The client reads two environment variables as defaults:
120
+
121
+ | Variable | Purpose |
122
+ |----------|---------|
123
+ | `ENSOUL_API_KEY` | API key (avoids passing `api_key=` in code) |
124
+ | `ENSOUL_BASE_URL` | API base URL (default: `https://api.ensoul-ai.com`) |
125
+
126
+ **Demo API** — the current hosted demo is available at:
127
+
128
+ ```bash
129
+ export ENSOUL_BASE_URL="https://api.demo.ensoul-ai.com"
130
+ export ENSOUL_API_KEY="your-api-key"
131
+ ```
132
+
133
+ With these set, `Ensoul()` connects to the demo with no constructor arguments.
134
+
135
+ You can also pass the base URL explicitly:
136
+
137
+ ```python
138
+ client = Ensoul(api_key="ens_...", base_url="https://api.demo.ensoul-ai.com")
139
+ ```
140
+
141
+ ## Authentication
142
+
143
+ **API key** (recommended):
144
+
145
+ ```python
146
+ client = Ensoul(api_key="ens_...")
147
+ # or set ENSOUL_API_KEY in the environment
148
+ client = Ensoul()
149
+ ```
150
+
151
+ **Bearer token**:
152
+
153
+ ```python
154
+ client = Ensoul(bearer_token="eyJ...")
155
+ ```
156
+
157
+ **OAuth2 token exchange** (client credentials flow):
158
+
159
+ ```python
160
+ token_response = client.auth.token(
161
+ grant_type="client_credentials",
162
+ client_id="your-client-id",
163
+ client_secret="your-client-secret",
164
+ )
165
+ authed_client = Ensoul(bearer_token=token_response.access_token)
166
+ ```
167
+
168
+ ## Resources
169
+
170
+ | Namespace | Description |
171
+ |-----------|-------------|
172
+ | `client.personas` | CRUD, list (paginated), batch create, personality vectors, filters, connections |
173
+ | `client.chat` | Send messages, streaming SSE, conversation history |
174
+ | `client.domains` | Domain configuration management |
175
+ | `client.simulations` | Time-based evolution simulations |
176
+ | `client.aggregate` | Aggregate queries with streaming results |
177
+ | `client.memory` | Persona memory management |
178
+ | `client.sessions` | Hierarchical session orchestration |
179
+ | `client.frameworks` | Framework management |
180
+ | `client.auth` | OAuth2 token exchange and API key management |
181
+ | `client.health` | Service health checks |
182
+ | `client.info` | Server info and configuration |
183
+
184
+ ## Requirements
185
+
186
+ - Python 3.11+
187
+ - [`httpx`](https://www.python-httpx.org/) — HTTP transport
188
+ - [`pydantic`](https://docs.pydantic.dev/) 2.x — request and response models
@@ -0,0 +1,75 @@
1
+ """Ensoul SDK Quickstart Example.
2
+
3
+ Set ENSOUL_API_KEY environment variable before running.
4
+
5
+ Usage:
6
+ python examples/quickstart.py
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import asyncio
12
+ import json
13
+
14
+ from ensoul import AsyncEnsoul, Ensoul, NotFoundError
15
+
16
+
17
+ def sync_example() -> None:
18
+ """Synchronous usage examples."""
19
+ client = Ensoul() # reads ENSOUL_API_KEY from env
20
+
21
+ # List domains
22
+ domains = client.domains.list()
23
+ print("Domains:")
24
+ for domain in domains.items:
25
+ print(f" {domain}")
26
+
27
+ # Create a persona
28
+ persona = client.personas.create(
29
+ name="Research Participant",
30
+ domain="example_domain",
31
+ personality_data={"openness": 75, "conscientiousness": 60},
32
+ )
33
+ print(f"\nCreated persona: {persona.id}")
34
+
35
+ # Chat
36
+ response = client.chat.send(persona.id, "What are your thoughts on technology?")
37
+ print(f"Response: {response.response}")
38
+
39
+ # Streaming chat
40
+ print("Streaming: ", end="")
41
+ for event in client.chat.stream(persona.id, "Tell me more."):
42
+ try:
43
+ data = json.loads(event.data)
44
+ if "chunk" in data:
45
+ print(data["chunk"], end="", flush=True)
46
+ except json.JSONDecodeError:
47
+ pass
48
+ print()
49
+
50
+ # Auto-pagination — iterates all pages automatically
51
+ print("\nAll personas:")
52
+ for p in client.personas.list(per_page=10).auto_paging_iter():
53
+ print(f" {p.name}")
54
+
55
+ # Error handling
56
+ try:
57
+ client.personas.get("nonexistent_id")
58
+ except NotFoundError as e:
59
+ print(f"\nExpected error: {e.message}")
60
+
61
+ client.close()
62
+
63
+
64
+ async def async_example() -> None:
65
+ """Async usage examples."""
66
+ async with AsyncEnsoul() as client:
67
+ personas = await client.personas.list()
68
+ print("Async personas:")
69
+ for p in personas.items:
70
+ print(f" {p.name}")
71
+
72
+
73
+ if __name__ == "__main__":
74
+ sync_example()
75
+ asyncio.run(async_example())
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "ensoul"
7
+ version = "0.1.0"
8
+ description = "Official Python SDK for the Ensoul API"
9
+ readme = "README.md"
10
+ license = "Apache-2.0"
11
+ requires-python = ">=3.11"
12
+ authors = [
13
+ { name = "Ensoul", email = "support@ensoul.ai" },
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Typing :: Typed",
22
+ ]
23
+ dependencies = [
24
+ "httpx>=0.25.0",
25
+ "pydantic>=2.0.0",
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://ensoul-ai.com"
30
+ Documentation = "https://ensoul-ai.com/products/studio/docs"
31
+ Repository = "https://github.com/ensoul-ai/ensoul-sdk"
32
+ Issues = "https://github.com/ensoul-ai/ensoul-sdk/issues"
33
+
34
+ [project.optional-dependencies]
35
+ dev = [
36
+ "pytest",
37
+ "pytest-asyncio",
38
+ "respx",
39
+ "ruff",
40
+ "mypy",
41
+ ]
42
+
43
+ [tool.hatch.build.targets.wheel]
44
+ packages = ["src/ensoul"]
45
+
46
+ [tool.ruff]
47
+ target-version = "py311"
48
+ line-length = 100
49
+
50
+ [tool.mypy]
51
+ python_version = "3.11"
52
+ strict = true
53
+
54
+ [tool.pytest.ini_options]
55
+ asyncio_mode = "auto"
@@ -0,0 +1,60 @@
1
+ """Ensoul SDK for Python."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from ensoul.client import AsyncEnsoul, Ensoul
6
+ from ensoul.config import ClientConfig
7
+ from ensoul.errors import (
8
+ APIError,
9
+ AuthenticationError,
10
+ AuthorizationError,
11
+ ConflictError,
12
+ EnsoulError,
13
+ NotFoundError,
14
+ RateLimitError,
15
+ ServerError,
16
+ ValidationError,
17
+ )
18
+ from ensoul.generated.auth import APIKeyResponse, TokenResponse, UserResponse
19
+ from ensoul.generated.chat import ChatRequest, ChatResponse, ConversationResponse
20
+ from ensoul.generated.enums import SessionStatus, SimulationStatus
21
+ from ensoul.generated.personas import (
22
+ PersonaBatchCreate,
23
+ PersonaBatchResponse,
24
+ PersonaCreate,
25
+ PersonaResponse,
26
+ PersonalityVectorResponse,
27
+ )
28
+
29
+ __version__ = "0.1.0"
30
+
31
+ __all__ = [
32
+ "Ensoul",
33
+ "AsyncEnsoul",
34
+ "ClientConfig",
35
+ # Errors
36
+ "EnsoulError",
37
+ "APIError",
38
+ "AuthenticationError",
39
+ "AuthorizationError",
40
+ "NotFoundError",
41
+ "RateLimitError",
42
+ "ValidationError",
43
+ "ConflictError",
44
+ "ServerError",
45
+ # Types
46
+ "PersonaCreate",
47
+ "PersonaResponse",
48
+ "PersonaBatchCreate",
49
+ "PersonaBatchResponse",
50
+ "PersonalityVectorResponse",
51
+ "ChatRequest",
52
+ "ChatResponse",
53
+ "ConversationResponse",
54
+ "TokenResponse",
55
+ "APIKeyResponse",
56
+ "UserResponse",
57
+ "SimulationStatus",
58
+ "SessionStatus",
59
+ "__version__",
60
+ ]
@@ -0,0 +1,29 @@
1
+ """Shared type aliases for the Ensoul SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Protocol, TypeVar, runtime_checkable
6
+
7
+ from pydantic import BaseModel
8
+
9
+ __all__ = [
10
+ "HeadersLike",
11
+ "QueryParams",
12
+ "RequestBody",
13
+ "T",
14
+ "PaginatedResponse",
15
+ ]
16
+
17
+ HeadersLike = dict[str, str]
18
+ QueryParams = dict[str, Any]
19
+ RequestBody = dict[str, Any] | BaseModel
20
+ T = TypeVar("T")
21
+
22
+
23
+ @runtime_checkable
24
+ class PaginatedResponse(Protocol):
25
+ items: list
26
+ total: int
27
+ page: int
28
+ per_page: int
29
+ pages: int