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.
- sinas/__init__.py +20 -0
- sinas/auth.py +100 -0
- sinas/chats.py +130 -0
- sinas/client.py +198 -0
- sinas/exceptions.py +41 -0
- sinas/executions.py +81 -0
- sinas/integrations/__init__.py +20 -0
- sinas/integrations/fastapi.py +288 -0
- sinas/integrations/routers.py +324 -0
- sinas/py.typed +0 -0
- sinas/state.py +164 -0
- sinas/webhooks.py +57 -0
- sinas-0.1.0.dist-info/METADATA +502 -0
- sinas-0.1.0.dist-info/RECORD +16 -0
- sinas-0.1.0.dist-info/WHEEL +4 -0
- sinas-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -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,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.
|