cycls 0.0.2.89__py3-none-any.whl → 0.0.2.91__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.
- cycls/app.py +5 -4
- cycls/state.py +6 -0
- cycls/themes/default/assets/index-BbLcHBku.js +435 -0
- cycls/themes/default/index.html +6 -2
- cycls/web.py +33 -25
- {cycls-0.0.2.89.dist-info → cycls-0.0.2.91.dist-info}/METADATA +18 -6
- cycls-0.0.2.91.dist-info/RECORD +15 -0
- cycls/themes/default/assets/index-C2r4Daz3.js +0 -435
- cycls/themes/default/assets/index-DWGS8zpa.css +0 -1
- cycls/themes/defaultN/assets/index-DOmNqb-2.js +0 -435
- cycls/themes/defaultN/index.html +0 -32
- cycls-0.0.2.89.dist-info/RECORD +0 -17
- /cycls/themes/{defaultN → default}/assets/index-oGkkm3Z8.css +0 -0
- {cycls-0.0.2.89.dist-info → cycls-0.0.2.91.dist-info}/WHEEL +0 -0
- {cycls-0.0.2.89.dist-info → cycls-0.0.2.91.dist-info}/entry_points.txt +0 -0
cycls/themes/default/index.html
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<title>AI Agent</title>
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<!-- Default SEO tags - dynamically updated by SEOHead component -->
|
|
8
|
+
<meta name="robots" content="noindex, nofollow" />
|
|
9
|
+
<meta name="googlebot" content="noindex, nofollow" />
|
|
10
|
+
<meta name="description" content="AI-powered chat interface" />
|
|
7
11
|
<script src="https://cdn.tailwindcss.com?plugins=forms,typography"></script>
|
|
8
12
|
<link
|
|
9
13
|
rel="stylesheet"
|
|
@@ -13,8 +17,8 @@
|
|
|
13
17
|
rel="stylesheet"
|
|
14
18
|
href="https://esm.sh/katex@0.16.8/dist/katex.min.css"
|
|
15
19
|
/>
|
|
16
|
-
<script type="module" crossorigin src="/assets/index-
|
|
17
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
20
|
+
<script type="module" crossorigin src="/assets/index-BbLcHBku.js"></script>
|
|
21
|
+
<link rel="stylesheet" crossorigin href="/assets/index-oGkkm3Z8.css">
|
|
18
22
|
</head>
|
|
19
23
|
<body style="overflow-x: hidden">
|
|
20
24
|
<div id="root"></div>
|
cycls/web.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json, inspect
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from pydantic import BaseModel
|
|
4
|
-
from typing import Optional
|
|
4
|
+
from typing import Optional, Union, Any
|
|
5
5
|
from .auth import PK_LIVE, PK_TEST, JWKS_PROD, JWKS_TEST
|
|
6
6
|
|
|
7
7
|
class Config(BaseModel):
|
|
@@ -16,7 +16,7 @@ class Config(BaseModel):
|
|
|
16
16
|
org: Optional[str] = None
|
|
17
17
|
pk: Optional[str] = None
|
|
18
18
|
jwks: Optional[str] = None
|
|
19
|
-
|
|
19
|
+
state: Union[bool, str] = False
|
|
20
20
|
|
|
21
21
|
def set_prod(self, prod: bool):
|
|
22
22
|
self.prod = prod
|
|
@@ -37,18 +37,13 @@ def sse(item):
|
|
|
37
37
|
if not isinstance(item, dict): item = {"type": "text", "text": item}
|
|
38
38
|
return f"data: {json.dumps(item)}\n\n"
|
|
39
39
|
|
|
40
|
-
async def encoder(stream
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
for item in stream:
|
|
48
|
-
if msg := sse(item): yield msg
|
|
49
|
-
except Exception as e:
|
|
50
|
-
error_msg = traceback.format_exc() if debug else str(e)
|
|
51
|
-
yield sse({"type": "thinking", "thinking": f"⚠️ Error\n```\n{error_msg}```"})
|
|
40
|
+
async def encoder(stream):
|
|
41
|
+
if inspect.isasyncgen(stream):
|
|
42
|
+
async for item in stream:
|
|
43
|
+
if msg := sse(item): yield msg
|
|
44
|
+
else:
|
|
45
|
+
for item in stream:
|
|
46
|
+
if msg := sse(item): yield msg
|
|
52
47
|
yield "data: [DONE]\n\n"
|
|
53
48
|
|
|
54
49
|
class Messages(list):
|
|
@@ -95,6 +90,9 @@ def web(func, config):
|
|
|
95
90
|
class Context(BaseModel):
|
|
96
91
|
messages: Any
|
|
97
92
|
user: Optional[User] = None
|
|
93
|
+
state: Optional[Any] = None
|
|
94
|
+
|
|
95
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
98
96
|
|
|
99
97
|
@property
|
|
100
98
|
def last_message(self) -> str:
|
|
@@ -102,6 +100,14 @@ def web(func, config):
|
|
|
102
100
|
return self.messages[-1].get("content", "")
|
|
103
101
|
return ""
|
|
104
102
|
|
|
103
|
+
@property
|
|
104
|
+
def kv(self):
|
|
105
|
+
return self.state.kv if self.state else None
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def fs(self):
|
|
109
|
+
return self.state.fs if self.state else None
|
|
110
|
+
|
|
105
111
|
app = FastAPI()
|
|
106
112
|
bearer_scheme = HTTPBearer()
|
|
107
113
|
|
|
@@ -123,23 +129,25 @@ def web(func, config):
|
|
|
123
129
|
@app.post("/chat/cycls")
|
|
124
130
|
@app.post("/chat/completions")
|
|
125
131
|
async def back(request: Request, jwt: Optional[dict] = Depends(validate) if config.auth else None):
|
|
126
|
-
import traceback
|
|
127
132
|
data = await request.json()
|
|
128
133
|
messages = data.get("messages")
|
|
129
134
|
user_data = jwt.get("user") if jwt else None
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
user = User(**user_data) if user_data else None
|
|
136
|
+
|
|
137
|
+
# Initialize state scoped to user
|
|
138
|
+
state_instance = None
|
|
139
|
+
if config.state:
|
|
140
|
+
from .state import create_state
|
|
141
|
+
user_id = user.id if user else "anonymous"
|
|
142
|
+
state_instance = await create_state(user_id)
|
|
143
|
+
|
|
144
|
+
context = Context(messages=Messages(messages), user=user, state=state_instance)
|
|
145
|
+
stream = await func(context) if inspect.iscoroutinefunction(func) else func(context)
|
|
146
|
+
|
|
139
147
|
if request.url.path == "/chat/completions":
|
|
140
148
|
stream = openai_encoder(stream)
|
|
141
149
|
elif request.url.path == "/chat/cycls":
|
|
142
|
-
stream = encoder(stream
|
|
150
|
+
stream = encoder(stream)
|
|
143
151
|
return StreamingResponse(stream, media_type="text/event-stream")
|
|
144
152
|
|
|
145
153
|
@app.get("/config")
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cycls
|
|
3
|
-
Version: 0.0.2.
|
|
3
|
+
Version: 0.0.2.91
|
|
4
4
|
Summary: Distribute Intelligence
|
|
5
5
|
Author-email: "Mohammed J. AlRujayi" <mj@cycls.com>
|
|
6
|
-
Requires-Python: >=3.
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: agentfs-sdk==0.4.0
|
|
7
8
|
Requires-Dist: cloudpickle>=3.1.1
|
|
8
9
|
Requires-Dist: docker>=7.1.0
|
|
9
10
|
Requires-Dist: email-validator>=2.0.0
|
|
@@ -11,6 +12,7 @@ Requires-Dist: fastapi>=0.111.0
|
|
|
11
12
|
Requires-Dist: httpx>=0.27.0
|
|
12
13
|
Requires-Dist: pyjwt>=2.8.0
|
|
13
14
|
Requires-Dist: uvicorn>=0.30.0
|
|
15
|
+
Requires-Dist: watchfiles>=1.0.0
|
|
14
16
|
Description-Content-Type: text/markdown
|
|
15
17
|
|
|
16
18
|
<h3 align="center">
|
|
@@ -19,7 +21,8 @@ Distribute Intelligence
|
|
|
19
21
|
|
|
20
22
|
<h4 align="center">
|
|
21
23
|
<a href="https://cycls.com">Website</a> |
|
|
22
|
-
<a href="https://docs.cycls.com">Docs</a>
|
|
24
|
+
<a href="https://docs.cycls.com">Docs</a> |
|
|
25
|
+
<a href="docs/tutorial.md">Tutorial</a>
|
|
23
26
|
</h4>
|
|
24
27
|
|
|
25
28
|
<h4 align="center">
|
|
@@ -79,7 +82,7 @@ app.deploy() # Live at https://agent.cycls.ai
|
|
|
79
82
|
pip install cycls
|
|
80
83
|
```
|
|
81
84
|
|
|
82
|
-
Requires Docker.
|
|
85
|
+
Requires Docker. See the [full tutorial](docs/tutorial.md) for a comprehensive guide.
|
|
83
86
|
|
|
84
87
|
## What You Get
|
|
85
88
|
|
|
@@ -102,6 +105,8 @@ Get an API key at [cycls.com](https://cycls.com).
|
|
|
102
105
|
|
|
103
106
|
## Authentication & Analytics
|
|
104
107
|
|
|
108
|
+
See the [tutorial](docs/tutorial.md#authentication) for full auth and monetization examples.
|
|
109
|
+
|
|
105
110
|
```python
|
|
106
111
|
@cycls.app(pip=["openai"], auth=True, analytics=True)
|
|
107
112
|
async def app(context):
|
|
@@ -118,7 +123,7 @@ async def app(context):
|
|
|
118
123
|
|
|
119
124
|
## Native UI Components
|
|
120
125
|
|
|
121
|
-
Yield structured objects for rich streaming responses
|
|
126
|
+
Yield structured objects for rich streaming responses. See the [tutorial](docs/tutorial.md#native-ui-components) for all component types and examples.
|
|
122
127
|
|
|
123
128
|
```python
|
|
124
129
|
@cycls.app()
|
|
@@ -193,7 +198,7 @@ See [docs/streaming-protocol.md](docs/streaming-protocol.md) for frontend integr
|
|
|
193
198
|
|
|
194
199
|
## Declarative Infrastructure
|
|
195
200
|
|
|
196
|
-
Define your entire runtime in the decorator
|
|
201
|
+
Define your entire runtime in the decorator. See the [tutorial](docs/tutorial.md#declarative-infrastructure) for more details.
|
|
197
202
|
|
|
198
203
|
```python
|
|
199
204
|
@cycls.app(
|
|
@@ -264,6 +269,13 @@ Access them at `https://your-app.cycls.ai/public/logo.png`.
|
|
|
264
269
|
|
|
265
270
|
No YAML. No Dockerfiles. No infrastructure repo. The code is the deployment.
|
|
266
271
|
|
|
272
|
+
## Learn More
|
|
273
|
+
|
|
274
|
+
- [Tutorial](docs/tutorial.md) - Comprehensive guide from basics to advanced
|
|
275
|
+
- [Streaming Protocol](docs/streaming-protocol.md) - Frontend integration
|
|
276
|
+
- [Runtime](docs/runtime.md) - Containerization details
|
|
277
|
+
- [Examples](examples/) - Working code samples
|
|
278
|
+
|
|
267
279
|
## License
|
|
268
280
|
|
|
269
281
|
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
cycls/__init__.py,sha256=efbq0vRijGOByKtz9bRF8WQFYmnPSgZV1DH-54s6iwQ,493
|
|
2
|
+
cycls/app.py,sha256=_-RoN8JuNE7fWSOHk80GpQ2GyaoXv-vtUWc_W8tDzm0,3243
|
|
3
|
+
cycls/auth.py,sha256=xkndHZyCfnlertMMEKerCJjf23N3fVcTRVTTSXTTuzg,247
|
|
4
|
+
cycls/cli.py,sha256=cVbIkTDnVofohvByyYUrXF_RYDQZVQECJqo7cPBPJfs,4781
|
|
5
|
+
cycls/function.py,sha256=FP94mCd5hfCASFwsTSYny7KOEsJOh3LME9oZgiVfgzo,14795
|
|
6
|
+
cycls/state.py,sha256=3RL_BqcbfiAkJ6byeEo4Q9L99VurYyYKYJJhJhEVmAo,210
|
|
7
|
+
cycls/web.py,sha256=v-hyWL9nlh4SyqAVgRzOkx96YuBntxqw6Q6phpAMDv0,6172
|
|
8
|
+
cycls/themes/default/index.html,sha256=_qizHg7Yb8jRvroVP_QJ4M8du1mUwI5VM04oIZjffWI,1082
|
|
9
|
+
cycls/themes/default/assets/index-BbLcHBku.js,sha256=ajrbPsIF5jxg-TrgpEkPoUL4WvyDvNB2Ss9zbJvRVOg,1357000
|
|
10
|
+
cycls/themes/default/assets/index-oGkkm3Z8.css,sha256=xHhbrJvvz8mIN_Otrl6nawKJcA41L3tCFhVEOstGhVU,6498
|
|
11
|
+
cycls/themes/dev/index.html,sha256=QJBHkdNuMMiwQU7o8dN8__8YQeQB45D37D-NCXIWB2Q,11585
|
|
12
|
+
cycls-0.0.2.91.dist-info/METADATA,sha256=I_CrgFp9ApDj-_UKD9RbX1wb5lYVTyaPVhTLQdFRooE,8829
|
|
13
|
+
cycls-0.0.2.91.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
14
|
+
cycls-0.0.2.91.dist-info/entry_points.txt,sha256=CktT5eNvW_Qxomf7L_Ez_GdUbL6qAfx_Utm6_HtUJwE,41
|
|
15
|
+
cycls-0.0.2.91.dist-info/RECORD,,
|