sinas 0.1.0__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.
@@ -0,0 +1,502 @@
1
+ Metadata-Version: 2.4
2
+ Name: sinas
3
+ Version: 0.1.0
4
+ Summary: Python SDK for SINAS - AI Agent Platform
5
+ Project-URL: Homepage, https://github.com/sinas/sinas-sdk
6
+ Project-URL: Documentation, https://docs.sinas.ai
7
+ Project-URL: Repository, https://github.com/sinas/sinas-sdk
8
+ Author: SINAS Team
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,ai,chatbot,fastapi,llm,mcp,sdk,sinas
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Framework :: FastAPI
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Internet :: WWW/HTTP
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Requires-Python: >=3.8
25
+ Requires-Dist: httpx>=0.24.0
26
+ Requires-Dist: pydantic>=2.0.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: black>=23.0.0; extra == 'dev'
29
+ Requires-Dist: fastapi>=0.100.0; extra == 'dev'
30
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
32
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
34
+ Requires-Dist: uvicorn>=0.23.0; extra == 'dev'
35
+ Provides-Extra: fastapi
36
+ Requires-Dist: email-validator>=2.0.0; extra == 'fastapi'
37
+ Requires-Dist: fastapi>=0.100.0; extra == 'fastapi'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # SINAS Python SDK
41
+
42
+ Python SDK for [SINAS](https://github.com/pulsr-ai/SINAS) - AI Agent & Automation Orchestration Platform.
43
+
44
+ **Runtime API Client** for executing agents, managing state, running webhooks, and tracking executions.
45
+
46
+ ## Installation
47
+
48
+ ```bash
49
+ pip install sinas
50
+ ```
51
+
52
+ With FastAPI integration:
53
+ ```bash
54
+ pip install sinas[fastapi]
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ ### Authentication
60
+
61
+ ```python
62
+ from sinas import SinasClient
63
+
64
+ # Initialize client with base URL
65
+ client = SinasClient(base_url="http://localhost:51245")
66
+
67
+ # Step 1: Login with email (sends OTP)
68
+ login_response = client.auth.login("user@example.com")
69
+ session_id = login_response["session_id"]
70
+
71
+ # Step 2: Verify OTP and get access + refresh tokens
72
+ response = client.auth.verify_otp(session_id, "123456")
73
+ # Tokens are automatically set on the client
74
+ access_token = response["access_token"]
75
+ refresh_token = response["refresh_token"]
76
+
77
+ # Or use an API key directly
78
+ client = SinasClient(
79
+ base_url="http://localhost:51245",
80
+ api_key="your-api-key"
81
+ )
82
+ ```
83
+
84
+ ### Environment Variables
85
+
86
+ Configure the client using environment variables:
87
+
88
+ ```bash
89
+ export SINAS_BASE_URL="http://localhost:51245"
90
+ export SINAS_API_KEY="your-api-key"
91
+ # or
92
+ export SINAS_TOKEN="your-jwt-token"
93
+ ```
94
+
95
+ ```python
96
+ from sinas import SinasClient
97
+
98
+ # Automatically uses environment variables
99
+ client = SinasClient()
100
+ ```
101
+
102
+ ## Core Features
103
+
104
+ ### State Management
105
+
106
+ Store and retrieve key-value data with namespacing and visibility controls:
107
+
108
+ ```python
109
+ # Create/set a state value
110
+ state = client.state.set(
111
+ namespace="user_prefs",
112
+ key="theme",
113
+ value={"mode": "dark", "accent": "blue"},
114
+ description="User theme preferences",
115
+ visibility="private" # private, group, or public
116
+ )
117
+
118
+ # Get a specific state
119
+ state = client.state.get(state["id"])
120
+ print(state["value"]) # {"mode": "dark", "accent": "blue"}
121
+
122
+ # List states with filtering
123
+ states = client.state.list(
124
+ namespace="user_prefs",
125
+ visibility="private",
126
+ tags="settings",
127
+ search="theme"
128
+ )
129
+
130
+ # Update state
131
+ updated = client.state.update(
132
+ state["id"],
133
+ value={"mode": "light", "accent": "green"}
134
+ )
135
+
136
+ # Delete state
137
+ client.state.delete(state["id"])
138
+ ```
139
+
140
+ ### Agent Chats
141
+
142
+ Create chats with agents and send messages:
143
+
144
+ ```python
145
+ # Create a chat with an agent
146
+ chat = client.chats.create(
147
+ namespace="customer-support",
148
+ agent_name="cs-agent-v1",
149
+ title="Customer Inquiry",
150
+ input={"customer_id": "12345"} # Optional input validated by agent
151
+ )
152
+
153
+ # Send a message (blocking)
154
+ response = client.chats.send(
155
+ chat_id=chat["id"],
156
+ content="What's the status of my order?"
157
+ )
158
+ print(response["content"])
159
+
160
+ # Stream a message (Server-Sent Events)
161
+ for chunk in client.chats.stream(
162
+ chat_id=chat["id"],
163
+ content="Tell me about your services"
164
+ ):
165
+ # Parse SSE data
166
+ import json
167
+ try:
168
+ data = json.loads(chunk)
169
+ if "content" in data:
170
+ print(data["content"], end="", flush=True)
171
+ except:
172
+ pass
173
+
174
+ # Get chat with all messages
175
+ chat_data = client.chats.get(chat["id"])
176
+ messages = chat_data["messages"]
177
+
178
+ # List all chats
179
+ chats = client.chats.list()
180
+
181
+ # Update chat
182
+ client.chats.update(chat["id"], title="Updated Title")
183
+
184
+ # Delete chat
185
+ client.chats.delete(chat["id"])
186
+ ```
187
+
188
+ ### Webhook Execution
189
+
190
+ Execute webhooks by path:
191
+
192
+ ```python
193
+ # Execute a webhook
194
+ result = client.webhooks.run(
195
+ path="process-payment",
196
+ method="POST",
197
+ body={"amount": 100, "currency": "USD"},
198
+ headers={"X-Custom-Header": "value"},
199
+ query={"idempotency_key": "abc123"}
200
+ )
201
+
202
+ print(result["execution_id"]) # Track execution
203
+ print(result["result"]) # Function output
204
+ ```
205
+
206
+ ### Executions
207
+
208
+ Track and manage function executions:
209
+
210
+ ```python
211
+ # List recent executions
212
+ executions = client.executions.list(
213
+ function_name="payment-processor",
214
+ status="completed",
215
+ limit=10
216
+ )
217
+
218
+ # Get execution details
219
+ execution = client.executions.get("execution-id")
220
+ print(execution["status"]) # running, completed, failed, awaiting_input
221
+ print(execution["output_data"])
222
+
223
+ # Get execution steps
224
+ steps = client.executions.get_steps("execution-id")
225
+ for step in steps:
226
+ print(f"{step['step_name']}: {step['status']}")
227
+
228
+ # Continue a paused execution
229
+ result = client.executions.continue_execution(
230
+ "execution-id",
231
+ input={"user_choice": "approve"}
232
+ )
233
+ ```
234
+
235
+ ### Authentication Methods
236
+
237
+ ```python
238
+ # Refresh access token
239
+ refreshed = client.auth.refresh(refresh_token)
240
+ new_access_token = refreshed["access_token"]
241
+
242
+ # Exchange external OIDC token
243
+ response = client.auth.external_auth(external_oidc_token)
244
+
245
+ # Get current user info
246
+ user = client.auth.get_me()
247
+ print(user["email"])
248
+
249
+ # Logout (revoke refresh token)
250
+ client.auth.logout(refresh_token)
251
+ ```
252
+
253
+ ## FastAPI Integration
254
+
255
+ SINAS provides **two powerful approaches** for FastAPI integration:
256
+
257
+ ### Approach 1: Ready-to-Mount Routers
258
+
259
+ Mount SINAS Runtime API endpoints directly in your FastAPI app with automatic authentication:
260
+
261
+ ```python
262
+ from fastapi import FastAPI
263
+ from sinas.integrations.routers import create_runtime_router
264
+
265
+ app = FastAPI()
266
+
267
+ # Mount ALL runtime endpoints at once
268
+ app.include_router(
269
+ create_runtime_router("http://localhost:51245", include_auth=False),
270
+ prefix="/api/runtime"
271
+ )
272
+
273
+ # This automatically creates endpoints like:
274
+ # - GET /api/runtime/states
275
+ # - POST /api/runtime/states
276
+ # - GET /api/runtime/chats
277
+ # - POST /api/runtime/agents/{namespace}/{agent}/chats
278
+ # - POST /api/runtime/webhooks/{path}
279
+ # - GET /api/runtime/executions
280
+ ```
281
+
282
+ Or mount individual routers:
283
+
284
+ ```python
285
+ from sinas.integrations.routers import (
286
+ create_state_router,
287
+ create_chat_router,
288
+ create_webhook_router,
289
+ create_executions_router
290
+ )
291
+
292
+ app.include_router(create_state_router("http://localhost:51245"), prefix="/runtime/states")
293
+ app.include_router(create_chat_router("http://localhost:51245"), prefix="/runtime/chats")
294
+ app.include_router(create_webhook_router("http://localhost:51245"), prefix="/runtime/webhooks")
295
+ app.include_router(create_executions_router("http://localhost:51245"), prefix="/runtime/executions")
296
+ ```
297
+
298
+ ### Approach 2: Custom Endpoints with SDK Client
299
+
300
+ Build custom endpoints with business logic using the authenticated client:
301
+
302
+ ```python
303
+ from fastapi import FastAPI, Depends
304
+ from sinas import SinasClient
305
+ from sinas.integrations.fastapi import SinasAuth
306
+
307
+ app = FastAPI()
308
+ sinas = SinasAuth(base_url="http://localhost:51245")
309
+
310
+ # Include auto-generated auth endpoints
311
+ app.include_router(sinas.router, prefix="/auth")
312
+
313
+ # Custom endpoint with auto-authentication
314
+ @app.get("/my-states")
315
+ async def get_my_states(client: SinasClient = Depends(sinas)):
316
+ """List user's states with custom filtering."""
317
+ states = client.state.list(limit=10)
318
+ return [{"id": s["id"], "key": s["key"]} for s in states]
319
+
320
+ # Combine multiple SDK calls
321
+ @app.post("/quick-chat")
322
+ async def quick_chat(
323
+ agent_namespace: str,
324
+ agent_name: str,
325
+ message: str,
326
+ client: SinasClient = Depends(sinas)
327
+ ):
328
+ """Create chat and send message in one request."""
329
+ chat = client.chats.create(agent_namespace, agent_name)
330
+ response = client.chats.send(chat["id"], message)
331
+ return {"chat_id": chat["id"], "response": response}
332
+
333
+ # Permission-protected endpoint
334
+ @app.post("/admin/cleanup")
335
+ async def cleanup_states(
336
+ namespace: str,
337
+ client: SinasClient = Depends(sinas.require("sinas.contexts.delete:all"))
338
+ ):
339
+ """Admin-only: Clean up states (requires permission)."""
340
+ states = client.state.list(namespace=namespace)
341
+ for state in states:
342
+ client.state.delete(state["id"])
343
+ return {"deleted": len(states)}
344
+ ```
345
+
346
+ ### Auto-Generated Auth Endpoints
347
+
348
+ The `sinas.router` automatically provides:
349
+
350
+ - `POST /auth/login` - Send OTP to email
351
+ - `POST /auth/verify-otp` - Verify OTP and get tokens
352
+ - `GET /auth/me` - Get current authenticated user
353
+
354
+ ### Permission-Based Access Control
355
+
356
+ Use `sinas.require()` to protect endpoints:
357
+
358
+ ```python
359
+ # Require specific permission
360
+ @app.delete("/states/{state_id}")
361
+ async def delete_state(
362
+ state_id: str,
363
+ client: SinasClient = Depends(sinas.require("sinas.contexts.delete:own"))
364
+ ):
365
+ client.state.delete(state_id)
366
+ return {"message": "Deleted"}
367
+
368
+ # Require multiple permissions (OR logic)
369
+ @app.post("/admin-action")
370
+ async def admin_action(
371
+ client: SinasClient = Depends(
372
+ sinas.require("sinas.admin:all", "sinas.contexts.write:all")
373
+ )
374
+ ):
375
+ return {"message": "Admin action completed"}
376
+ ```
377
+
378
+ ### Complete Example
379
+
380
+ See [examples/fastapi_app.py](examples/fastapi_app.py) for a complete working example with both approaches.
381
+
382
+ Run it with:
383
+ ```bash
384
+ uvicorn examples.fastapi_app:app --reload
385
+ ```
386
+
387
+ Then visit `http://localhost:8000/docs` for interactive API documentation.
388
+
389
+ ## Context Manager
390
+
391
+ The client can be used as a context manager for proper resource cleanup:
392
+
393
+ ```python
394
+ with SinasClient(base_url="http://localhost:51245") as client:
395
+ states = client.state.list()
396
+ # Client is automatically closed when exiting
397
+ ```
398
+
399
+ ## Error Handling
400
+
401
+ ```python
402
+ from sinas import (
403
+ SinasClient,
404
+ SinasAPIError,
405
+ SinasAuthError,
406
+ SinasNotFoundError,
407
+ SinasValidationError
408
+ )
409
+
410
+ client = SinasClient(base_url="http://localhost:51245")
411
+
412
+ try:
413
+ state = client.state.get("non-existent-id")
414
+ except SinasNotFoundError as e:
415
+ print(f"State not found: {e}")
416
+ except SinasAuthError as e:
417
+ print(f"Authentication failed: {e}")
418
+ except SinasValidationError as e:
419
+ print(f"Validation error: {e}")
420
+ except SinasAPIError as e:
421
+ print(f"API error: {e}")
422
+ print(f"Status code: {e.status_code}")
423
+ print(f"Response: {e.response}")
424
+ ```
425
+
426
+ ## API Reference
427
+
428
+ ### SinasClient
429
+
430
+ #### `auth`
431
+ - `login(email)` - Send OTP to email
432
+ - `verify_otp(session_id, otp_code)` - Verify OTP and get tokens
433
+ - `external_auth(token)` - Exchange external OIDC token
434
+ - `refresh(refresh_token)` - Refresh access token
435
+ - `logout(refresh_token)` - Revoke refresh token
436
+ - `get_me()` - Get current user info
437
+
438
+ #### `state`
439
+ - `set(namespace, key, value, ...)` - Create/update state
440
+ - `get(state_id)` - Get state by ID
441
+ - `list(namespace?, visibility?, ...)` - List states with filters
442
+ - `update(state_id, value?, ...)` - Update state
443
+ - `delete(state_id)` - Delete state
444
+
445
+ #### `chats`
446
+ - `create(namespace, agent_name, input?, title?)` - Create chat with agent
447
+ - `send(chat_id, content)` - Send message (blocking)
448
+ - `stream(chat_id, content)` - Send message (streaming SSE)
449
+ - `get(chat_id)` - Get chat with messages
450
+ - `list()` - List user's chats
451
+ - `update(chat_id, title?)` - Update chat
452
+ - `delete(chat_id)` - Delete chat
453
+
454
+ #### `webhooks`
455
+ - `run(path, method?, body?, headers?, query?)` - Execute webhook
456
+
457
+ #### `executions`
458
+ - `list(function_name?, status?, skip?, limit?)` - List executions
459
+ - `get(execution_id)` - Get execution details
460
+ - `get_steps(execution_id)` - Get execution steps
461
+ - `continue_execution(execution_id, input)` - Continue paused execution
462
+
463
+ ### FastAPI Integration
464
+
465
+ #### `SinasAuth(base_url, auto_error=True)`
466
+ FastAPI dependency for authentication and authorization.
467
+
468
+ #### Router Functions
469
+ - `create_runtime_router(base_url, include_auth=False)` - Complete runtime router
470
+ - `create_state_router(base_url, prefix="")` - State endpoints
471
+ - `create_chat_router(base_url, prefix="")` - Chat endpoints
472
+ - `create_webhook_router(base_url, prefix="")` - Webhook endpoints
473
+ - `create_executions_router(base_url, prefix="")` - Execution endpoints
474
+
475
+ ## Development
476
+
477
+ ### Install Development Dependencies
478
+
479
+ ```bash
480
+ pip install -e ".[dev]"
481
+ ```
482
+
483
+ ### Run Examples
484
+
485
+ ```bash
486
+ # Basic usage
487
+ python examples/basic_usage.py
488
+
489
+ # FastAPI app
490
+ uvicorn examples.fastapi_app:app --reload
491
+ ```
492
+
493
+ ### Code Formatting
494
+
495
+ ```bash
496
+ black sinas
497
+ ruff check sinas
498
+ ```
499
+
500
+ ## License
501
+
502
+ MIT
@@ -0,0 +1,16 @@
1
+ sinas/__init__.py,sha256=nt3SVKS-tSfjDwNirNSFth0xQGOEZYkuEUQQRtX7APQ,398
2
+ sinas/auth.py,sha256=zd78eYhmJ5EhVLvKj3I3d001OYjEsXM0Vieri9NHLH8,3222
3
+ sinas/chats.py,sha256=zgQpY7rlveREuwjFXLhLHGxt3YnTBU9aLbaB50ZfVl4,3371
4
+ sinas/client.py,sha256=1i2l5KFsTrKb_tLWg4y9vBXUKOyxo4R_yY5U_5Ww56M,5964
5
+ sinas/exceptions.py,sha256=ERTw8uPaGtkroAQhxDij7p5EY_-YiKJmGnuvjWBBNZI,815
6
+ sinas/executions.py,sha256=wB4tS57zFpt149oIxO2B-bnY2t_DiZP3sTteiHHAR5A,2323
7
+ sinas/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ sinas/state.py,sha256=J7Ol6QFu08WPnYQI0uroOnq7pEt6htArDT3Xjz88o8o,5315
9
+ sinas/webhooks.py,sha256=mz1IXBSYjc8B_n3dPbhmMcT0ItrvQ-zuyr3PrqStsfE,1665
10
+ sinas/integrations/__init__.py,sha256=pMVqIo30O0LQaWK7qtspgxsI0QUpxxYGTpz87_ShuTo,480
11
+ sinas/integrations/fastapi.py,sha256=yNLez_OP-eef7Nr-2j2v09RdukU0DarHj58jmXWk5YE,9419
12
+ sinas/integrations/routers.py,sha256=H60DpU1n-GPNcm2qPKP0P0pFXgcRmqxvVcLaF8FM-rE,9908
13
+ sinas-0.1.0.dist-info/METADATA,sha256=PPGwuYC0tv93qy7Q83W_v0kqaodUOcUFgYaxhVGe8Yk,13156
14
+ sinas-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
15
+ sinas-0.1.0.dist-info/licenses/LICENSE,sha256=rxZIwhvDtoCgD8-unmNYMBi2HelS5mkblOffT9hhiXQ,1062
16
+ sinas-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 SINAS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.