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
sinas/__init__.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""SINAS Python SDK - AI Agent Platform Client."""
|
|
2
|
+
|
|
3
|
+
from sinas.client import SinasClient
|
|
4
|
+
from sinas.exceptions import (
|
|
5
|
+
SinasError,
|
|
6
|
+
SinasAPIError,
|
|
7
|
+
SinasAuthError,
|
|
8
|
+
SinasNotFoundError,
|
|
9
|
+
SinasValidationError,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__version__ = "0.1.0"
|
|
13
|
+
__all__ = [
|
|
14
|
+
"SinasClient",
|
|
15
|
+
"SinasError",
|
|
16
|
+
"SinasAPIError",
|
|
17
|
+
"SinasAuthError",
|
|
18
|
+
"SinasNotFoundError",
|
|
19
|
+
"SinasValidationError",
|
|
20
|
+
]
|
sinas/auth.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Runtime Authentication API."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from sinas.client import SinasClient
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AuthAPI:
|
|
10
|
+
"""Runtime Authentication API methods."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, client: "SinasClient") -> None:
|
|
13
|
+
self._client = client
|
|
14
|
+
|
|
15
|
+
def login(self, email: str) -> Dict[str, Any]:
|
|
16
|
+
"""Initiate login by sending OTP to email.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
email: User's email address.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
Login response with message and session_id.
|
|
23
|
+
Example: {"message": "OTP sent to your email", "session_id": "uuid-here"}
|
|
24
|
+
"""
|
|
25
|
+
return self._client._request("POST", "/auth/login", json={"email": email})
|
|
26
|
+
|
|
27
|
+
def verify_otp(self, session_id: str, otp_code: str) -> Dict[str, Any]:
|
|
28
|
+
"""Verify OTP and get access + refresh tokens.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
session_id: Session ID from login() response.
|
|
32
|
+
otp_code: One-time password code from email.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Response with access token, refresh token, and user info.
|
|
36
|
+
Example: {"access_token": "jwt-token", "refresh_token": "refresh-token",
|
|
37
|
+
"token_type": "bearer", "expires_in": 900, "user": {...}}
|
|
38
|
+
"""
|
|
39
|
+
response = self._client._request(
|
|
40
|
+
"POST", "/auth/verify-otp",
|
|
41
|
+
json={"session_id": session_id, "otp_code": otp_code}
|
|
42
|
+
)
|
|
43
|
+
# Automatically set the token on the client
|
|
44
|
+
if "access_token" in response:
|
|
45
|
+
self._client.set_token(response["access_token"])
|
|
46
|
+
return response
|
|
47
|
+
|
|
48
|
+
def external_auth(self, token: str) -> Dict[str, Any]:
|
|
49
|
+
"""Exchange external OIDC token for SINAS JWT.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
token: External OIDC token.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Response with access token, refresh token, and user info.
|
|
56
|
+
"""
|
|
57
|
+
response = self._client._request(
|
|
58
|
+
"POST", "/auth/external-auth",
|
|
59
|
+
json={"token": token}
|
|
60
|
+
)
|
|
61
|
+
if "access_token" in response:
|
|
62
|
+
self._client.set_token(response["access_token"])
|
|
63
|
+
return response
|
|
64
|
+
|
|
65
|
+
def refresh(self, refresh_token: str) -> Dict[str, Any]:
|
|
66
|
+
"""Refresh access token using refresh token.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
refresh_token: Refresh token from login/verify response.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Response with new access token.
|
|
73
|
+
Example: {"access_token": "jwt-token", "token_type": "bearer", "expires_in": 900}
|
|
74
|
+
"""
|
|
75
|
+
response = self._client._request(
|
|
76
|
+
"POST", "/auth/refresh",
|
|
77
|
+
json={"refresh_token": refresh_token}
|
|
78
|
+
)
|
|
79
|
+
if "access_token" in response:
|
|
80
|
+
self._client.set_token(response["access_token"])
|
|
81
|
+
return response
|
|
82
|
+
|
|
83
|
+
def logout(self, refresh_token: str) -> None:
|
|
84
|
+
"""Logout by revoking refresh token.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
refresh_token: Refresh token to revoke.
|
|
88
|
+
"""
|
|
89
|
+
self._client._request(
|
|
90
|
+
"POST", "/auth/logout",
|
|
91
|
+
json={"refresh_token": refresh_token}
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
def get_me(self) -> Dict[str, Any]:
|
|
95
|
+
"""Get current authenticated user info.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
User information.
|
|
99
|
+
"""
|
|
100
|
+
return self._client._request("GET", "/auth/me")
|
sinas/chats.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""Runtime Chats API."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Union
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from sinas.client import SinasClient
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ChatsAPI:
|
|
10
|
+
"""Runtime Chats API methods."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, client: "SinasClient") -> None:
|
|
13
|
+
self._client = client
|
|
14
|
+
|
|
15
|
+
def create(
|
|
16
|
+
self,
|
|
17
|
+
namespace: str,
|
|
18
|
+
agent_name: str,
|
|
19
|
+
input: Optional[Dict[str, Any]] = None,
|
|
20
|
+
title: Optional[str] = None,
|
|
21
|
+
) -> Dict[str, Any]:
|
|
22
|
+
"""Create a new chat with an agent.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
namespace: Agent namespace.
|
|
26
|
+
agent_name: Agent name.
|
|
27
|
+
input: Optional input data validated against agent's input_schema.
|
|
28
|
+
title: Optional chat title.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Created chat information.
|
|
32
|
+
"""
|
|
33
|
+
data: Dict[str, Any] = {}
|
|
34
|
+
if input is not None:
|
|
35
|
+
data["input"] = input
|
|
36
|
+
if title is not None:
|
|
37
|
+
data["title"] = title
|
|
38
|
+
|
|
39
|
+
return self._client._request(
|
|
40
|
+
"POST",
|
|
41
|
+
f"/agents/{namespace}/{agent_name}/chats",
|
|
42
|
+
json=data
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def send(
|
|
46
|
+
self,
|
|
47
|
+
chat_id: str,
|
|
48
|
+
content: Union[str, List[Dict[str, Any]]],
|
|
49
|
+
) -> Dict[str, Any]:
|
|
50
|
+
"""Send message to chat and get response (blocking).
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
chat_id: Chat ID (UUID).
|
|
54
|
+
content: Message content (string or list of content blocks).
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
Message response from the agent.
|
|
58
|
+
"""
|
|
59
|
+
return self._client._request(
|
|
60
|
+
"POST",
|
|
61
|
+
f"/chats/{chat_id}/messages",
|
|
62
|
+
json={"content": content}
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def stream(
|
|
66
|
+
self,
|
|
67
|
+
chat_id: str,
|
|
68
|
+
content: Union[str, List[Dict[str, Any]]],
|
|
69
|
+
) -> Iterator[str]:
|
|
70
|
+
"""Send message to chat and stream response via SSE.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
chat_id: Chat ID (UUID).
|
|
74
|
+
content: Message content (string or list of content blocks).
|
|
75
|
+
|
|
76
|
+
Yields:
|
|
77
|
+
Server-sent event data chunks.
|
|
78
|
+
"""
|
|
79
|
+
return self._client._stream(
|
|
80
|
+
"POST",
|
|
81
|
+
f"/chats/{chat_id}/messages/stream",
|
|
82
|
+
json={"content": content}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def get(self, chat_id: str) -> Dict[str, Any]:
|
|
86
|
+
"""Get a chat with all messages.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
chat_id: Chat ID (UUID).
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Chat information with messages.
|
|
93
|
+
"""
|
|
94
|
+
return self._client._request("GET", f"/chats/{chat_id}")
|
|
95
|
+
|
|
96
|
+
def list(self) -> List[Dict[str, Any]]:
|
|
97
|
+
"""List all chats for the current user.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
List of chats.
|
|
101
|
+
"""
|
|
102
|
+
return self._client._request("GET", "/chats")
|
|
103
|
+
|
|
104
|
+
def update(
|
|
105
|
+
self,
|
|
106
|
+
chat_id: str,
|
|
107
|
+
title: Optional[str] = None,
|
|
108
|
+
) -> Dict[str, Any]:
|
|
109
|
+
"""Update a chat.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
chat_id: Chat ID (UUID).
|
|
113
|
+
title: New title.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Updated chat information.
|
|
117
|
+
"""
|
|
118
|
+
data: Dict[str, Any] = {}
|
|
119
|
+
if title is not None:
|
|
120
|
+
data["title"] = title
|
|
121
|
+
|
|
122
|
+
return self._client._request("PUT", f"/chats/{chat_id}", json=data)
|
|
123
|
+
|
|
124
|
+
def delete(self, chat_id: str) -> None:
|
|
125
|
+
"""Delete a chat and all its messages.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
chat_id: Chat ID (UUID).
|
|
129
|
+
"""
|
|
130
|
+
self._client._request("DELETE", f"/chats/{chat_id}")
|
sinas/client.py
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""SINAS SDK client."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import Any, Dict, Iterator, Optional
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
from sinas.auth import AuthAPI
|
|
9
|
+
from sinas.chats import ChatsAPI
|
|
10
|
+
from sinas.executions import ExecutionsAPI
|
|
11
|
+
from sinas.exceptions import SinasAPIError, SinasAuthError, SinasNotFoundError, SinasValidationError
|
|
12
|
+
from sinas.state import StateAPI
|
|
13
|
+
from sinas.webhooks import WebhooksAPI
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SinasClient:
|
|
17
|
+
"""SINAS Runtime API client."""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
base_url: Optional[str] = None,
|
|
22
|
+
api_key: Optional[str] = None,
|
|
23
|
+
token: Optional[str] = None,
|
|
24
|
+
timeout: float = 30.0,
|
|
25
|
+
) -> None:
|
|
26
|
+
"""Initialize SINAS Runtime client.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
base_url: Base URL for SINAS API. Defaults to SINAS_BASE_URL env var.
|
|
30
|
+
api_key: API key for authentication. Defaults to SINAS_API_KEY env var.
|
|
31
|
+
token: JWT token for authentication. Defaults to SINAS_TOKEN env var.
|
|
32
|
+
timeout: Request timeout in seconds.
|
|
33
|
+
"""
|
|
34
|
+
self.base_url = (base_url or os.getenv("SINAS_BASE_URL", "")).rstrip("/")
|
|
35
|
+
if not self.base_url:
|
|
36
|
+
raise ValueError(
|
|
37
|
+
"base_url must be provided or SINAS_BASE_URL environment variable must be set"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
self._api_key = api_key or os.getenv("SINAS_API_KEY")
|
|
41
|
+
self._token = token or os.getenv("SINAS_TOKEN")
|
|
42
|
+
self._timeout = timeout
|
|
43
|
+
|
|
44
|
+
self._client = httpx.Client(timeout=timeout)
|
|
45
|
+
|
|
46
|
+
# Initialize Runtime API modules
|
|
47
|
+
self.auth = AuthAPI(self)
|
|
48
|
+
self.state = StateAPI(self)
|
|
49
|
+
self.chats = ChatsAPI(self)
|
|
50
|
+
self.webhooks = WebhooksAPI(self)
|
|
51
|
+
self.executions = ExecutionsAPI(self)
|
|
52
|
+
|
|
53
|
+
def __enter__(self) -> "SinasClient":
|
|
54
|
+
return self
|
|
55
|
+
|
|
56
|
+
def __exit__(self, *args: Any) -> None:
|
|
57
|
+
self.close()
|
|
58
|
+
|
|
59
|
+
def close(self) -> None:
|
|
60
|
+
"""Close the HTTP client."""
|
|
61
|
+
self._client.close()
|
|
62
|
+
|
|
63
|
+
def _get_headers(self) -> Dict[str, str]:
|
|
64
|
+
"""Get headers for API requests."""
|
|
65
|
+
headers = {"Content-Type": "application/json"}
|
|
66
|
+
|
|
67
|
+
if self._token:
|
|
68
|
+
headers["Authorization"] = f"Bearer {self._token}"
|
|
69
|
+
elif self._api_key:
|
|
70
|
+
headers["Authorization"] = f"Bearer {self._api_key}"
|
|
71
|
+
|
|
72
|
+
return headers
|
|
73
|
+
|
|
74
|
+
def _request(
|
|
75
|
+
self,
|
|
76
|
+
method: str,
|
|
77
|
+
path: str,
|
|
78
|
+
json: Optional[Dict[str, Any]] = None,
|
|
79
|
+
params: Optional[Dict[str, Any]] = None,
|
|
80
|
+
) -> Any:
|
|
81
|
+
"""Make an HTTP request to the API.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
method: HTTP method (GET, POST, PUT, DELETE, PATCH).
|
|
85
|
+
path: API path (without base URL).
|
|
86
|
+
json: JSON request body.
|
|
87
|
+
params: Query parameters.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Response data.
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
SinasAPIError: If the request fails.
|
|
94
|
+
"""
|
|
95
|
+
url = f"{self.base_url}{path}"
|
|
96
|
+
headers = self._get_headers()
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
response = self._client.request(
|
|
100
|
+
method=method,
|
|
101
|
+
url=url,
|
|
102
|
+
json=json,
|
|
103
|
+
params=params,
|
|
104
|
+
headers=headers,
|
|
105
|
+
)
|
|
106
|
+
self._handle_response(response)
|
|
107
|
+
|
|
108
|
+
if response.status_code == 204:
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
return response.json()
|
|
112
|
+
except httpx.HTTPError as e:
|
|
113
|
+
raise SinasAPIError(f"HTTP request failed: {e}")
|
|
114
|
+
|
|
115
|
+
def _stream(
|
|
116
|
+
self,
|
|
117
|
+
method: str,
|
|
118
|
+
path: str,
|
|
119
|
+
json: Optional[Dict[str, Any]] = None,
|
|
120
|
+
) -> Iterator[str]:
|
|
121
|
+
"""Make a streaming HTTP request to the API.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
method: HTTP method.
|
|
125
|
+
path: API path (without base URL).
|
|
126
|
+
json: JSON request body.
|
|
127
|
+
|
|
128
|
+
Yields:
|
|
129
|
+
Server-sent event data.
|
|
130
|
+
|
|
131
|
+
Raises:
|
|
132
|
+
SinasAPIError: If the request fails.
|
|
133
|
+
"""
|
|
134
|
+
url = f"{self.base_url}{path}"
|
|
135
|
+
headers = self._get_headers()
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
with self._client.stream(
|
|
139
|
+
method=method,
|
|
140
|
+
url=url,
|
|
141
|
+
json=json,
|
|
142
|
+
headers=headers,
|
|
143
|
+
) as response:
|
|
144
|
+
self._handle_response(response)
|
|
145
|
+
for line in response.iter_lines():
|
|
146
|
+
if line.startswith("data: "):
|
|
147
|
+
yield line[6:]
|
|
148
|
+
except httpx.HTTPError as e:
|
|
149
|
+
raise SinasAPIError(f"HTTP streaming request failed: {e}")
|
|
150
|
+
|
|
151
|
+
def _handle_response(self, response: httpx.Response) -> None:
|
|
152
|
+
"""Handle HTTP response and raise appropriate exceptions.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
response: HTTP response.
|
|
156
|
+
|
|
157
|
+
Raises:
|
|
158
|
+
SinasAuthError: If authentication fails.
|
|
159
|
+
SinasNotFoundError: If resource is not found.
|
|
160
|
+
SinasValidationError: If validation fails.
|
|
161
|
+
SinasAPIError: For other API errors.
|
|
162
|
+
"""
|
|
163
|
+
if response.is_success:
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
error_data = response.json()
|
|
168
|
+
except Exception:
|
|
169
|
+
error_data = {}
|
|
170
|
+
|
|
171
|
+
message = error_data.get("detail", f"HTTP {response.status_code}")
|
|
172
|
+
|
|
173
|
+
if response.status_code == 401:
|
|
174
|
+
raise SinasAuthError(message, status_code=response.status_code, response=error_data)
|
|
175
|
+
elif response.status_code == 404:
|
|
176
|
+
raise SinasNotFoundError(message, status_code=response.status_code, response=error_data)
|
|
177
|
+
elif response.status_code == 422:
|
|
178
|
+
raise SinasValidationError(
|
|
179
|
+
message, status_code=response.status_code, response=error_data
|
|
180
|
+
)
|
|
181
|
+
else:
|
|
182
|
+
raise SinasAPIError(message, status_code=response.status_code, response=error_data)
|
|
183
|
+
|
|
184
|
+
def set_token(self, token: str) -> None:
|
|
185
|
+
"""Set the authentication token.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
token: JWT token.
|
|
189
|
+
"""
|
|
190
|
+
self._token = token
|
|
191
|
+
|
|
192
|
+
def set_api_key(self, api_key: str) -> None:
|
|
193
|
+
"""Set the API key.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
api_key: API key.
|
|
197
|
+
"""
|
|
198
|
+
self._api_key = api_key
|
sinas/exceptions.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""SINAS SDK exceptions."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SinasError(Exception):
|
|
7
|
+
"""Base exception for SINAS SDK."""
|
|
8
|
+
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SinasAPIError(SinasError):
|
|
13
|
+
"""Exception raised for API errors."""
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
message: str,
|
|
18
|
+
status_code: Optional[int] = None,
|
|
19
|
+
response: Optional[Dict[str, Any]] = None,
|
|
20
|
+
) -> None:
|
|
21
|
+
super().__init__(message)
|
|
22
|
+
self.status_code = status_code
|
|
23
|
+
self.response = response
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SinasAuthError(SinasAPIError):
|
|
27
|
+
"""Exception raised for authentication errors."""
|
|
28
|
+
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SinasNotFoundError(SinasAPIError):
|
|
33
|
+
"""Exception raised when a resource is not found."""
|
|
34
|
+
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class SinasValidationError(SinasAPIError):
|
|
39
|
+
"""Exception raised for validation errors."""
|
|
40
|
+
|
|
41
|
+
pass
|
sinas/executions.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Runtime Executions API."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from sinas.client import SinasClient
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ExecutionsAPI:
|
|
10
|
+
"""Runtime Executions API methods."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, client: "SinasClient") -> None:
|
|
13
|
+
self._client = client
|
|
14
|
+
|
|
15
|
+
def list(
|
|
16
|
+
self,
|
|
17
|
+
function_name: Optional[str] = None,
|
|
18
|
+
status: Optional[str] = None,
|
|
19
|
+
skip: int = 0,
|
|
20
|
+
limit: int = 100,
|
|
21
|
+
) -> List[Dict[str, Any]]:
|
|
22
|
+
"""List function executions.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
function_name: Filter by function name.
|
|
26
|
+
status: Filter by execution status (running, completed, failed, awaiting_input).
|
|
27
|
+
skip: Number of executions to skip (pagination).
|
|
28
|
+
limit: Maximum number of executions to return (1-1000).
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
List of executions.
|
|
32
|
+
"""
|
|
33
|
+
params: Dict[str, Any] = {"skip": skip, "limit": limit}
|
|
34
|
+
if function_name is not None:
|
|
35
|
+
params["function_name"] = function_name
|
|
36
|
+
if status is not None:
|
|
37
|
+
params["status"] = status
|
|
38
|
+
|
|
39
|
+
return self._client._request("GET", "/executions", params=params)
|
|
40
|
+
|
|
41
|
+
def get(self, execution_id: str) -> Dict[str, Any]:
|
|
42
|
+
"""Get a specific execution.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
execution_id: Execution ID.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Execution details.
|
|
49
|
+
"""
|
|
50
|
+
return self._client._request("GET", f"/executions/{execution_id}")
|
|
51
|
+
|
|
52
|
+
def get_steps(self, execution_id: str) -> List[Dict[str, Any]]:
|
|
53
|
+
"""Get all steps for an execution.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
execution_id: Execution ID.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
List of execution steps.
|
|
60
|
+
"""
|
|
61
|
+
return self._client._request("GET", f"/executions/{execution_id}/steps")
|
|
62
|
+
|
|
63
|
+
def continue_execution(
|
|
64
|
+
self,
|
|
65
|
+
execution_id: str,
|
|
66
|
+
input: Dict[str, Any],
|
|
67
|
+
) -> Dict[str, Any]:
|
|
68
|
+
"""Continue a paused execution with user input.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
execution_id: Execution ID.
|
|
72
|
+
input: User input data.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Continuation response with execution status, output_data, or next prompt.
|
|
76
|
+
"""
|
|
77
|
+
return self._client._request(
|
|
78
|
+
"POST",
|
|
79
|
+
f"/executions/{execution_id}/continue",
|
|
80
|
+
json={"input": input}
|
|
81
|
+
)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""SINAS integrations for web frameworks."""
|
|
2
|
+
|
|
3
|
+
from sinas.integrations.fastapi import SinasAuth, SinasFastAPI
|
|
4
|
+
from sinas.integrations.routers import (
|
|
5
|
+
create_chat_router,
|
|
6
|
+
create_executions_router,
|
|
7
|
+
create_runtime_router,
|
|
8
|
+
create_state_router,
|
|
9
|
+
create_webhook_router,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"SinasAuth",
|
|
14
|
+
"SinasFastAPI",
|
|
15
|
+
"create_runtime_router",
|
|
16
|
+
"create_state_router",
|
|
17
|
+
"create_chat_router",
|
|
18
|
+
"create_webhook_router",
|
|
19
|
+
"create_executions_router",
|
|
20
|
+
]
|