shadow-os 1.0.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.
@@ -0,0 +1,7 @@
1
+ # Build artifacts — generated by `python -m build`, never source.
2
+ dist/
3
+ build/
4
+ *.egg-info/
5
+ __pycache__/
6
+ .pytest_cache/
7
+ .mypy_cache/
@@ -0,0 +1,281 @@
1
+ Metadata-Version: 2.5
2
+ Name: shadow-os
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for Shadow-OS — build, operate and talk to AI agents.
5
+ Project-URL: Homepage, https://shadow-os-ai.vercel.app
6
+ Project-URL: Documentation, https://shadow-os-ai.vercel.app/developers
7
+ Project-URL: Source, https://github.com/daniel-sha/ai_web
8
+ Project-URL: Issues, https://github.com/daniel-sha/ai_web/issues
9
+ Author: Shadow-OS
10
+ License: MIT
11
+ Keywords: agents,ai,chatbot,llm,rag,sdk,shadow-os,whatsapp
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: Implementation :: CPython
23
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.9
27
+ Requires-Dist: anyio>=3.6
28
+ Requires-Dist: httpx>=0.24
29
+ Provides-Extra: dev
30
+ Requires-Dist: mypy>=1.8; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
32
+ Requires-Dist: pytest>=7.4; extra == 'dev'
33
+ Requires-Dist: respx>=0.20; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Shadow-OS Python SDK
37
+
38
+ The official Python client for [Shadow-OS](https://shadow-os-ai.vercel.app) — build, operate and talk to AI agents.
39
+
40
+ ```bash
41
+ pip install shadow-os
42
+ ```
43
+
44
+ ```python
45
+ from shadow_os import ShadowOS
46
+
47
+ with ShadowOS() as client: # reads $SHADOW_OS_API_KEY
48
+ print(client.chat("Summarise the notes I uploaded yesterday"))
49
+ ```
50
+
51
+ - **Typed** — every response is a dataclass, the package ships `py.typed`, and unknown server fields stay reachable via `.raw`.
52
+ - **Sync and async** — `ShadowOS` and `AsyncShadowOS` share one definition per endpoint, so they cannot drift.
53
+ - **Resilient** — timeouts, exponential backoff with jitter, `Retry-After` support, and automatic retries for cold starts and 5xx.
54
+ - **Complete** — everything the platform can do, not just chat: agents, knowledge, access links, customers, escalations, appointments, analytics.
55
+
56
+ ---
57
+
58
+ ## Authentication
59
+
60
+ Two credentials, for two different jobs.
61
+
62
+ | Credential | Looks like | Use it for |
63
+ |---|---|---|
64
+ | **Account key** | `sk-shadow-…` | Your account: chat, documents, and managing agents you own. |
65
+ | **Agent token / share code** | `sk-agent-…` / `lnk_…` | Talking *to* one configured agent, as your end-users do. |
66
+
67
+ ```python
68
+ client = ShadowOS("sk-shadow-…") # or set SHADOW_OS_API_KEY
69
+ agent = AgentClient("lnk_…") # or set SHADOW_OS_AGENT_TOKEN
70
+ ```
71
+
72
+ Create an account key at [/developers](https://shadow-os-ai.vercel.app/developers).
73
+
74
+ ---
75
+
76
+ ## Your account assistant
77
+
78
+ ```python
79
+ reply = client.chat("What did we agree with Dana?", session_id="conv-42")
80
+ print(reply.answer, reply.usage)
81
+ ```
82
+
83
+ `session_id` is an **isolation boundary**, not just a label: memory, uploaded files and search are scoped to
84
+ it, so one end-user can never see another's. Pass `scope="account"` to opt into the shared account space
85
+ (which also has access to connected integrations such as Gmail).
86
+
87
+ ### Documents & semantic search
88
+
89
+ ```python
90
+ client.documents.upload("handbook.pdf", session_id="conv-42")
91
+ for doc in client.documents.list(session_id="conv-42"):
92
+ print(doc.name)
93
+
94
+ for hit in client.documents.search("refund policy", top_k=5, session_id="conv-42"):
95
+ print(hit.score, hit.source, hit.text[:120])
96
+ ```
97
+
98
+ ### Quota
99
+
100
+ ```python
101
+ u = client.usage()
102
+ print(f"{u.used}/{u.quota} used — {u.remaining} left")
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Building an agent
108
+
109
+ ```python
110
+ from shadow_os import ShadowOS, AgentConfig
111
+
112
+ client = ShadowOS()
113
+
114
+ created = client.agents.create(
115
+ name="Nona Pizza",
116
+ template="pizzeria", # or persona="..." for full control
117
+ fields={"business_name": "Nona", "hours": "Sun–Thu 11:00–23:00"},
118
+ config=AgentConfig(memory_mode="single", tone="warm and brief"),
119
+ )
120
+ print(created.id, created.manager_token) # the token is shown ONCE — store it now
121
+ ```
122
+
123
+ Browse what's available before you build:
124
+
125
+ ```python
126
+ for t in client.templates():
127
+ print(t.id, t.name, [f["id"] for f in t.fields])
128
+
129
+ print(client.tool_catalog().groups) # optional tool bundles you can enable per agent
130
+ ```
131
+
132
+ ### Teaching it
133
+
134
+ ```python
135
+ agent = client.agent(created.id)
136
+
137
+ agent.knowledge.add_file("menu.pdf", description="Full menu with prices")
138
+ agent.knowledge.add_file("storefront.jpg") # images are understood AND sendable to customers
139
+ agent.knowledge.add_url("https://nona.example/about")
140
+ agent.knowledge.add_text("We deliver within 4km. Closed on holidays.", name="policies")
141
+
142
+ agent.knowledge.add_sendable("invoice-template.pdf") # deliverable, but NOT searchable knowledge
143
+ ```
144
+
145
+ ### Sharing it
146
+
147
+ ```python
148
+ link = agent.share_link() # persistent, created once, stable forever
149
+ print(link.web, link.whatsapp)
150
+
151
+ staff = agent.access.create_share_link(role="manager", label="Front desk")
152
+ api = agent.access.create_token(role="member", label="Website widget")
153
+ ```
154
+
155
+ ### Operating it
156
+
157
+ ```python
158
+ for c in agent.customers():
159
+ print(c.display_name, "·", c.profile)
160
+
161
+ for e in agent.escalations():
162
+ agent.answer_escalation(e.id, "Yes — we're open until 23:00 on Sunday.")
163
+
164
+ print(agent.analytics().raw)
165
+ print(agent.appointments())
166
+ print(agent.delivery_status())
167
+ ```
168
+
169
+ Talk to it **as its manager** — it sees your customer roster and acts with your authority:
170
+
171
+ ```python
172
+ print(agent.talk("Message Dana that her order is ready"))
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Talking to an agent (what you embed)
178
+
179
+ ```python
180
+ from shadow_os import AgentClient
181
+
182
+ with AgentClient("lnk_…") as agent:
183
+ info = agent.info()
184
+ print(info["agent_name"], info["welcome"])
185
+
186
+ reply = agent.send("Are you open on Sunday?", member_key="user-7f3c")
187
+ print(reply.answer, reply.files)
188
+ ```
189
+
190
+ `member_key` is the identity of the person you are speaking for. Give each end-user a **stable, unguessable**
191
+ id and each gets private, durable memory and history inside the agent — they can never see each other.
192
+
193
+ ```python
194
+ dana = agent.for_member("user-7f3c", member_name="Dana") # shares the connection pool
195
+ for conv in dana.conversations():
196
+ print(conv.session_id, conv.title)
197
+ for msg in dana.history(session_id="main"):
198
+ print(msg.role, msg.content)
199
+ ```
200
+
201
+ ---
202
+
203
+ ## Async
204
+
205
+ Identical surface, awaited:
206
+
207
+ ```python
208
+ from shadow_os import AsyncShadowOS
209
+
210
+ async with AsyncShadowOS() as client:
211
+ reply = await client.chat("hello")
212
+ agents = await client.agents.list()
213
+ stats = await client.agent(agents[0].id).analytics()
214
+ ```
215
+
216
+ ---
217
+
218
+ ## Errors
219
+
220
+ ```python
221
+ from shadow_os import QuotaExceeded, RateLimited, ShadowOSError
222
+
223
+ try:
224
+ client.chat("hello")
225
+ except QuotaExceeded as e:
226
+ print("out of quota:", e.usage)
227
+ except RateLimited as e:
228
+ print("slow down, retry in", e.retry_after)
229
+ except ShadowOSError as e:
230
+ print(e.status, e.code, e.message, e.request_id)
231
+ ```
232
+
233
+ Every error carries `status`, `code`, `message` and — when the server sent one — `request_id`. Quote that id
234
+ in a support request and the exact call can be found in the logs.
235
+
236
+ | Exception | HTTP |
237
+ |---|---|
238
+ | `BadRequestError` | 400 / 422 |
239
+ | `AuthenticationError` | 401 |
240
+ | `QuotaExceeded` | 402 |
241
+ | `PermissionDeniedError` | 403 |
242
+ | `NotFoundError` | 404 |
243
+ | `ConflictError` | 409 |
244
+ | `PayloadTooLarge` | 413 |
245
+ | `RateLimited` | 429 |
246
+ | `ServerError` / `ServiceUnavailable` | 5xx |
247
+ | `APITimeoutError` / `APIConnectionError` | no response |
248
+
249
+ ---
250
+
251
+ ## Configuration
252
+
253
+ ```python
254
+ client = ShadowOS(
255
+ api_key="sk-shadow-…", # or $SHADOW_OS_API_KEY
256
+ base_url="https://…", # or $SHADOW_OS_BASE_URL — for self-hosting or staging
257
+ timeout=120.0, # per request; generous on purpose (the service can cold-start)
258
+ max_retries=3, # timeouts, connection errors, 429 and 5xx
259
+ )
260
+ ```
261
+
262
+ Bring your own `httpx` client (proxies, custom TLS, shared pools):
263
+
264
+ ```python
265
+ import httpx
266
+ client = ShadowOS(http_client=httpx.Client(proxies="http://…", timeout=60))
267
+ ```
268
+
269
+ Retries use exponential backoff with full jitter. `Retry-After` always wins. 4xx responses other than 429
270
+ are never retried — they will not become a 200.
271
+
272
+ ---
273
+
274
+ ## Development
275
+
276
+ ```bash
277
+ pip install -e ".[dev]"
278
+ pytest
279
+ ```
280
+
281
+ MIT licensed.
@@ -0,0 +1,246 @@
1
+ # Shadow-OS Python SDK
2
+
3
+ The official Python client for [Shadow-OS](https://shadow-os-ai.vercel.app) — build, operate and talk to AI agents.
4
+
5
+ ```bash
6
+ pip install shadow-os
7
+ ```
8
+
9
+ ```python
10
+ from shadow_os import ShadowOS
11
+
12
+ with ShadowOS() as client: # reads $SHADOW_OS_API_KEY
13
+ print(client.chat("Summarise the notes I uploaded yesterday"))
14
+ ```
15
+
16
+ - **Typed** — every response is a dataclass, the package ships `py.typed`, and unknown server fields stay reachable via `.raw`.
17
+ - **Sync and async** — `ShadowOS` and `AsyncShadowOS` share one definition per endpoint, so they cannot drift.
18
+ - **Resilient** — timeouts, exponential backoff with jitter, `Retry-After` support, and automatic retries for cold starts and 5xx.
19
+ - **Complete** — everything the platform can do, not just chat: agents, knowledge, access links, customers, escalations, appointments, analytics.
20
+
21
+ ---
22
+
23
+ ## Authentication
24
+
25
+ Two credentials, for two different jobs.
26
+
27
+ | Credential | Looks like | Use it for |
28
+ |---|---|---|
29
+ | **Account key** | `sk-shadow-…` | Your account: chat, documents, and managing agents you own. |
30
+ | **Agent token / share code** | `sk-agent-…` / `lnk_…` | Talking *to* one configured agent, as your end-users do. |
31
+
32
+ ```python
33
+ client = ShadowOS("sk-shadow-…") # or set SHADOW_OS_API_KEY
34
+ agent = AgentClient("lnk_…") # or set SHADOW_OS_AGENT_TOKEN
35
+ ```
36
+
37
+ Create an account key at [/developers](https://shadow-os-ai.vercel.app/developers).
38
+
39
+ ---
40
+
41
+ ## Your account assistant
42
+
43
+ ```python
44
+ reply = client.chat("What did we agree with Dana?", session_id="conv-42")
45
+ print(reply.answer, reply.usage)
46
+ ```
47
+
48
+ `session_id` is an **isolation boundary**, not just a label: memory, uploaded files and search are scoped to
49
+ it, so one end-user can never see another's. Pass `scope="account"` to opt into the shared account space
50
+ (which also has access to connected integrations such as Gmail).
51
+
52
+ ### Documents & semantic search
53
+
54
+ ```python
55
+ client.documents.upload("handbook.pdf", session_id="conv-42")
56
+ for doc in client.documents.list(session_id="conv-42"):
57
+ print(doc.name)
58
+
59
+ for hit in client.documents.search("refund policy", top_k=5, session_id="conv-42"):
60
+ print(hit.score, hit.source, hit.text[:120])
61
+ ```
62
+
63
+ ### Quota
64
+
65
+ ```python
66
+ u = client.usage()
67
+ print(f"{u.used}/{u.quota} used — {u.remaining} left")
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Building an agent
73
+
74
+ ```python
75
+ from shadow_os import ShadowOS, AgentConfig
76
+
77
+ client = ShadowOS()
78
+
79
+ created = client.agents.create(
80
+ name="Nona Pizza",
81
+ template="pizzeria", # or persona="..." for full control
82
+ fields={"business_name": "Nona", "hours": "Sun–Thu 11:00–23:00"},
83
+ config=AgentConfig(memory_mode="single", tone="warm and brief"),
84
+ )
85
+ print(created.id, created.manager_token) # the token is shown ONCE — store it now
86
+ ```
87
+
88
+ Browse what's available before you build:
89
+
90
+ ```python
91
+ for t in client.templates():
92
+ print(t.id, t.name, [f["id"] for f in t.fields])
93
+
94
+ print(client.tool_catalog().groups) # optional tool bundles you can enable per agent
95
+ ```
96
+
97
+ ### Teaching it
98
+
99
+ ```python
100
+ agent = client.agent(created.id)
101
+
102
+ agent.knowledge.add_file("menu.pdf", description="Full menu with prices")
103
+ agent.knowledge.add_file("storefront.jpg") # images are understood AND sendable to customers
104
+ agent.knowledge.add_url("https://nona.example/about")
105
+ agent.knowledge.add_text("We deliver within 4km. Closed on holidays.", name="policies")
106
+
107
+ agent.knowledge.add_sendable("invoice-template.pdf") # deliverable, but NOT searchable knowledge
108
+ ```
109
+
110
+ ### Sharing it
111
+
112
+ ```python
113
+ link = agent.share_link() # persistent, created once, stable forever
114
+ print(link.web, link.whatsapp)
115
+
116
+ staff = agent.access.create_share_link(role="manager", label="Front desk")
117
+ api = agent.access.create_token(role="member", label="Website widget")
118
+ ```
119
+
120
+ ### Operating it
121
+
122
+ ```python
123
+ for c in agent.customers():
124
+ print(c.display_name, "·", c.profile)
125
+
126
+ for e in agent.escalations():
127
+ agent.answer_escalation(e.id, "Yes — we're open until 23:00 on Sunday.")
128
+
129
+ print(agent.analytics().raw)
130
+ print(agent.appointments())
131
+ print(agent.delivery_status())
132
+ ```
133
+
134
+ Talk to it **as its manager** — it sees your customer roster and acts with your authority:
135
+
136
+ ```python
137
+ print(agent.talk("Message Dana that her order is ready"))
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Talking to an agent (what you embed)
143
+
144
+ ```python
145
+ from shadow_os import AgentClient
146
+
147
+ with AgentClient("lnk_…") as agent:
148
+ info = agent.info()
149
+ print(info["agent_name"], info["welcome"])
150
+
151
+ reply = agent.send("Are you open on Sunday?", member_key="user-7f3c")
152
+ print(reply.answer, reply.files)
153
+ ```
154
+
155
+ `member_key` is the identity of the person you are speaking for. Give each end-user a **stable, unguessable**
156
+ id and each gets private, durable memory and history inside the agent — they can never see each other.
157
+
158
+ ```python
159
+ dana = agent.for_member("user-7f3c", member_name="Dana") # shares the connection pool
160
+ for conv in dana.conversations():
161
+ print(conv.session_id, conv.title)
162
+ for msg in dana.history(session_id="main"):
163
+ print(msg.role, msg.content)
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Async
169
+
170
+ Identical surface, awaited:
171
+
172
+ ```python
173
+ from shadow_os import AsyncShadowOS
174
+
175
+ async with AsyncShadowOS() as client:
176
+ reply = await client.chat("hello")
177
+ agents = await client.agents.list()
178
+ stats = await client.agent(agents[0].id).analytics()
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Errors
184
+
185
+ ```python
186
+ from shadow_os import QuotaExceeded, RateLimited, ShadowOSError
187
+
188
+ try:
189
+ client.chat("hello")
190
+ except QuotaExceeded as e:
191
+ print("out of quota:", e.usage)
192
+ except RateLimited as e:
193
+ print("slow down, retry in", e.retry_after)
194
+ except ShadowOSError as e:
195
+ print(e.status, e.code, e.message, e.request_id)
196
+ ```
197
+
198
+ Every error carries `status`, `code`, `message` and — when the server sent one — `request_id`. Quote that id
199
+ in a support request and the exact call can be found in the logs.
200
+
201
+ | Exception | HTTP |
202
+ |---|---|
203
+ | `BadRequestError` | 400 / 422 |
204
+ | `AuthenticationError` | 401 |
205
+ | `QuotaExceeded` | 402 |
206
+ | `PermissionDeniedError` | 403 |
207
+ | `NotFoundError` | 404 |
208
+ | `ConflictError` | 409 |
209
+ | `PayloadTooLarge` | 413 |
210
+ | `RateLimited` | 429 |
211
+ | `ServerError` / `ServiceUnavailable` | 5xx |
212
+ | `APITimeoutError` / `APIConnectionError` | no response |
213
+
214
+ ---
215
+
216
+ ## Configuration
217
+
218
+ ```python
219
+ client = ShadowOS(
220
+ api_key="sk-shadow-…", # or $SHADOW_OS_API_KEY
221
+ base_url="https://…", # or $SHADOW_OS_BASE_URL — for self-hosting or staging
222
+ timeout=120.0, # per request; generous on purpose (the service can cold-start)
223
+ max_retries=3, # timeouts, connection errors, 429 and 5xx
224
+ )
225
+ ```
226
+
227
+ Bring your own `httpx` client (proxies, custom TLS, shared pools):
228
+
229
+ ```python
230
+ import httpx
231
+ client = ShadowOS(http_client=httpx.Client(proxies="http://…", timeout=60))
232
+ ```
233
+
234
+ Retries use exponential backoff with full jitter. `Retry-After` always wins. 4xx responses other than 429
235
+ are never retried — they will not become a 200.
236
+
237
+ ---
238
+
239
+ ## Development
240
+
241
+ ```bash
242
+ pip install -e ".[dev]"
243
+ pytest
244
+ ```
245
+
246
+ MIT licensed.
@@ -0,0 +1,65 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.21"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "shadow-os"
7
+ dynamic = ["version"]
8
+ description = "Official Python SDK for Shadow-OS — build, operate and talk to AI agents."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Shadow-OS" }]
13
+ keywords = ["shadow-os", "ai", "agents", "llm", "chatbot", "whatsapp", "rag", "sdk"]
14
+ classifiers = [
15
+ "Development Status :: 5 - Production/Stable",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: Implementation :: CPython",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
28
+ "Typing :: Typed",
29
+ ]
30
+ dependencies = [
31
+ "httpx>=0.24",
32
+ "anyio>=3.6",
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ dev = [
37
+ "pytest>=7.4",
38
+ "pytest-asyncio>=0.23",
39
+ "respx>=0.20",
40
+ "mypy>=1.8",
41
+ ]
42
+
43
+ [project.urls]
44
+ Homepage = "https://shadow-os-ai.vercel.app"
45
+ Documentation = "https://shadow-os-ai.vercel.app/developers"
46
+ Source = "https://github.com/daniel-sha/ai_web"
47
+ Issues = "https://github.com/daniel-sha/ai_web/issues"
48
+
49
+ [tool.hatch.version]
50
+ path = "src/shadow_os/_version.py"
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["src/shadow_os"]
54
+
55
+ [tool.hatch.build.targets.sdist]
56
+ include = ["src/shadow_os", "README.md", "tests"]
57
+
58
+ [tool.pytest.ini_options]
59
+ testpaths = ["tests"]
60
+ asyncio_mode = "auto"
61
+
62
+ [tool.mypy]
63
+ python_version = "3.9"
64
+ warn_unused_ignores = true
65
+ ignore_missing_imports = true
@@ -0,0 +1,79 @@
1
+ """Shadow-OS — the official Python SDK.
2
+
3
+ Build on Shadow-OS from Python: talk to your account assistant, manage documents and semantic search, and
4
+ create + operate configured business agents end to end (knowledge, access links, customers, escalations,
5
+ appointments, analytics).
6
+
7
+ Quickstart::
8
+
9
+ from shadow_os import ShadowOS
10
+
11
+ with ShadowOS() as client: # reads $SHADOW_OS_API_KEY
12
+ print(client.chat("hello"))
13
+
14
+ See https://shadow-os-ai.vercel.app/developers for the full API reference.
15
+ """
16
+ from ._version import __version__
17
+ from .client import (
18
+ AgentClient,
19
+ AgentHandle,
20
+ AsyncAgentClient,
21
+ AsyncAgentHandle,
22
+ AsyncShadowOS,
23
+ ShadowOS,
24
+ )
25
+ from .errors import (
26
+ APIConnectionError,
27
+ APIStatusError,
28
+ APITimeoutError,
29
+ AuthenticationError,
30
+ BadRequestError,
31
+ ConflictError,
32
+ NotFoundError,
33
+ PayloadTooLarge,
34
+ PermissionDeniedError,
35
+ QuotaExceeded,
36
+ RateLimited,
37
+ ServerError,
38
+ ServiceUnavailable,
39
+ ShadowOSError,
40
+ )
41
+ from .models import (
42
+ Agent,
43
+ AgentConfig,
44
+ AgentReply,
45
+ AgentToken,
46
+ Analytics,
47
+ Appointment,
48
+ ChatResponse,
49
+ Conversation,
50
+ CreatedAgent,
51
+ DeliveryStatus,
52
+ Document,
53
+ Escalation,
54
+ KnowledgeItem,
55
+ Member,
56
+ Message,
57
+ PrimaryShareLink,
58
+ SearchHit,
59
+ SearchResults,
60
+ ShareLink,
61
+ Template,
62
+ ToolCatalog,
63
+ Usage,
64
+ )
65
+
66
+ __all__ = [
67
+ "__version__",
68
+ # clients
69
+ "ShadowOS", "AsyncShadowOS", "AgentClient", "AsyncAgentClient", "AgentHandle", "AsyncAgentHandle",
70
+ # models
71
+ "Agent", "AgentConfig", "AgentReply", "AgentToken", "Analytics", "Appointment", "ChatResponse",
72
+ "Conversation", "CreatedAgent", "DeliveryStatus", "Document", "Escalation", "KnowledgeItem",
73
+ "Member", "Message", "PrimaryShareLink", "SearchHit", "SearchResults", "ShareLink", "Template",
74
+ "ToolCatalog", "Usage",
75
+ # errors
76
+ "ShadowOSError", "APIConnectionError", "APITimeoutError", "APIStatusError", "BadRequestError",
77
+ "AuthenticationError", "PermissionDeniedError", "NotFoundError", "ConflictError", "QuotaExceeded",
78
+ "RateLimited", "PayloadTooLarge", "ServerError", "ServiceUnavailable",
79
+ ]