cycls 0.0.2.20__tar.gz → 0.0.2.21__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.
- cycls-0.0.2.21/PKG-INFO +92 -0
- cycls-0.0.2.21/README.md +73 -0
- {cycls-0.0.2.20 → cycls-0.0.2.21}/cycls/cycls.py +34 -27
- {cycls-0.0.2.20 → cycls-0.0.2.21}/pyproject.toml +1 -1
- cycls-0.0.2.20/PKG-INFO +0 -68
- cycls-0.0.2.20/README.md +0 -49
- {cycls-0.0.2.20 → cycls-0.0.2.21}/cycls/__init__.py +0 -0
- {cycls-0.0.2.20 → cycls-0.0.2.21}/cycls/tuns +0 -0
cycls-0.0.2.21/PKG-INFO
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cycls
|
|
3
|
+
Version: 0.0.2.21
|
|
4
|
+
Summary: Cycls SDK
|
|
5
|
+
Author: Mohammed Jamal
|
|
6
|
+
Author-email: mj@cycls.com
|
|
7
|
+
Requires-Python: >=3.8,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Requires-Dist: asyncssh (>=2.14.2,<3.0.0)
|
|
15
|
+
Requires-Dist: fastapi (>=0.111.0,<0.112.0)
|
|
16
|
+
Requires-Dist: httpx (>=0.27.0,<0.28.0)
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
</br></br>
|
|
20
|
+
<p align="center">
|
|
21
|
+
<picture>
|
|
22
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://cycls.com/static/assets/logo-gold.svg">
|
|
23
|
+
<source media="(prefers-color-scheme: light)" srcset="https://cycls.com/static/assets/logo.svg">
|
|
24
|
+
<img alt="Cycls" src="https://cycls.com/static/assets/logo.svg" width="150">
|
|
25
|
+
</picture>
|
|
26
|
+
</p>
|
|
27
|
+
</br></br>
|
|
28
|
+
|
|
29
|
+
<div align="center">
|
|
30
|
+
<a href="https://pypi.org/project/cycls/" target="_blank" rel="noopener noreferrer">
|
|
31
|
+
<img loading="lazy" src="https://img.shields.io/pypi/v/cycls.svg" alt="PyPI" class="img_ev3q" style="display: inline;">
|
|
32
|
+
</a>
|
|
33
|
+
<a href="https://discord.gg/BMnaMatDC7" target="_blank" rel="noopener noreferrer">
|
|
34
|
+
<img loading="lazy" src="https://img.shields.io/discord/1175782747164389466" alt="Discord" class="img_ev3q" style="display: inline;">
|
|
35
|
+
</a>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
</br>
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pip install cycls
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
# Apps ✦
|
|
45
|
+
Instantly publish and share AI apps
|
|
46
|
+
|
|
47
|
+
```py
|
|
48
|
+
from cycls import Cycls
|
|
49
|
+
|
|
50
|
+
cycls = Cycls()
|
|
51
|
+
|
|
52
|
+
@cycls("@spark")
|
|
53
|
+
def app(x):
|
|
54
|
+
return x.content + "from spark"
|
|
55
|
+
|
|
56
|
+
cycls.push()
|
|
57
|
+
```
|
|
58
|
+
`cycls.push()` will then publish the app `@spark` on [cycls.com/@spark](https://cycls.com/@spark)
|
|
59
|
+
## Async Apps
|
|
60
|
+
For performance, make the function asynchronous. The following is an async app with message `history` and session `id`
|
|
61
|
+
```py
|
|
62
|
+
from cycls import Cycls
|
|
63
|
+
|
|
64
|
+
cycls = Cycls()
|
|
65
|
+
|
|
66
|
+
@cycls("@spark")
|
|
67
|
+
async def app(x):
|
|
68
|
+
print(x.history, x.id)
|
|
69
|
+
return x.content + "from spark"
|
|
70
|
+
|
|
71
|
+
cycls.push()
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
# Agents ✧
|
|
75
|
+
Call any public app as an agent, see [explore](https://explore.cycls.com)
|
|
76
|
+
```py
|
|
77
|
+
from cycls import Cycls
|
|
78
|
+
|
|
79
|
+
cycls = Cycls()
|
|
80
|
+
|
|
81
|
+
@cycls("@spark")
|
|
82
|
+
async def app(x):
|
|
83
|
+
return cycls.call("@groq",
|
|
84
|
+
x.content)
|
|
85
|
+
|
|
86
|
+
cycls.push()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Try it live
|
|
90
|
+
- [cycls.com/@groq](https://cycls.com/@groq) | [groq.py](https://github.com/Cycls/examples/blob/main/groq.py)
|
|
91
|
+
- [cycls.com/@openai](https://cycls.com/@openai) | [openai.py](https://github.com/Cycls/examples/blob/main/openai.py)
|
|
92
|
+
|
cycls-0.0.2.21/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
</br></br>
|
|
2
|
+
<p align="center">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://cycls.com/static/assets/logo-gold.svg">
|
|
5
|
+
<source media="(prefers-color-scheme: light)" srcset="https://cycls.com/static/assets/logo.svg">
|
|
6
|
+
<img alt="Cycls" src="https://cycls.com/static/assets/logo.svg" width="150">
|
|
7
|
+
</picture>
|
|
8
|
+
</p>
|
|
9
|
+
</br></br>
|
|
10
|
+
|
|
11
|
+
<div align="center">
|
|
12
|
+
<a href="https://pypi.org/project/cycls/" target="_blank" rel="noopener noreferrer">
|
|
13
|
+
<img loading="lazy" src="https://img.shields.io/pypi/v/cycls.svg" alt="PyPI" class="img_ev3q" style="display: inline;">
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://discord.gg/BMnaMatDC7" target="_blank" rel="noopener noreferrer">
|
|
16
|
+
<img loading="lazy" src="https://img.shields.io/discord/1175782747164389466" alt="Discord" class="img_ev3q" style="display: inline;">
|
|
17
|
+
</a>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
</br>
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
pip install cycls
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
# Apps ✦
|
|
27
|
+
Instantly publish and share AI apps
|
|
28
|
+
|
|
29
|
+
```py
|
|
30
|
+
from cycls import Cycls
|
|
31
|
+
|
|
32
|
+
cycls = Cycls()
|
|
33
|
+
|
|
34
|
+
@cycls("@spark")
|
|
35
|
+
def app(x):
|
|
36
|
+
return x.content + "from spark"
|
|
37
|
+
|
|
38
|
+
cycls.push()
|
|
39
|
+
```
|
|
40
|
+
`cycls.push()` will then publish the app `@spark` on [cycls.com/@spark](https://cycls.com/@spark)
|
|
41
|
+
## Async Apps
|
|
42
|
+
For performance, make the function asynchronous. The following is an async app with message `history` and session `id`
|
|
43
|
+
```py
|
|
44
|
+
from cycls import Cycls
|
|
45
|
+
|
|
46
|
+
cycls = Cycls()
|
|
47
|
+
|
|
48
|
+
@cycls("@spark")
|
|
49
|
+
async def app(x):
|
|
50
|
+
print(x.history, x.id)
|
|
51
|
+
return x.content + "from spark"
|
|
52
|
+
|
|
53
|
+
cycls.push()
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
# Agents ✧
|
|
57
|
+
Call any public app as an agent, see [explore](https://explore.cycls.com)
|
|
58
|
+
```py
|
|
59
|
+
from cycls import Cycls
|
|
60
|
+
|
|
61
|
+
cycls = Cycls()
|
|
62
|
+
|
|
63
|
+
@cycls("@spark")
|
|
64
|
+
async def app(x):
|
|
65
|
+
return cycls.call("@groq",
|
|
66
|
+
x.content)
|
|
67
|
+
|
|
68
|
+
cycls.push()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Try it live
|
|
72
|
+
- [cycls.com/@groq](https://cycls.com/@groq) | [groq.py](https://github.com/Cycls/examples/blob/main/groq.py)
|
|
73
|
+
- [cycls.com/@openai](https://cycls.com/@openai) | [openai.py](https://github.com/Cycls/examples/blob/main/openai.py)
|
|
@@ -10,7 +10,7 @@ import inspect
|
|
|
10
10
|
import logging
|
|
11
11
|
logging.basicConfig(level=logging.ERROR)
|
|
12
12
|
|
|
13
|
-
O = lambda x,y: print(f"✦/✧ {str(x).ljust(
|
|
13
|
+
O = lambda x,y: print(f"✦/✧ {str(x).ljust(11)} | {y}")
|
|
14
14
|
|
|
15
15
|
import os
|
|
16
16
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
@@ -38,31 +38,34 @@ async def create_ssh_tunnel(x,y,z='tuns.sh'):
|
|
|
38
38
|
listener = await conn.forward_remote_port(x, 80, 'localhost', y)
|
|
39
39
|
O("tunnel","open");print(" ")
|
|
40
40
|
await listener.wait_closed()
|
|
41
|
+
O("tunnel", "closed")
|
|
41
42
|
except (OSError, asyncssh.Error) as e:
|
|
42
43
|
O("tunnel",f"disconnected ({e})")
|
|
43
44
|
|
|
44
|
-
def register(handles,
|
|
45
|
+
def register(handles, net, url, email):
|
|
45
46
|
try:
|
|
46
47
|
with httpx.Client() as client:
|
|
47
|
-
response = client.post(f"{
|
|
48
|
+
response = client.post(f"{net}/register", json={"handles":handles, "url":url, "email":email})
|
|
48
49
|
if response.status_code==200:
|
|
49
50
|
data = (response.json()).get("content")
|
|
50
51
|
for i in data:
|
|
51
|
-
O(i[0],f"{
|
|
52
|
+
O(i[0],f"{net}/{i[1]}")
|
|
52
53
|
else:
|
|
53
54
|
print("✦/✧ failed to register ⚠️")
|
|
54
55
|
except Exception as e:
|
|
55
56
|
print(f"An error occurred: {e}")
|
|
56
57
|
|
|
57
58
|
class Cycls:
|
|
58
|
-
def __init__(self, url="",
|
|
59
|
+
def __init__(self, url="", net="https://cycls.com", port=find_available_port(8001), email=None):
|
|
59
60
|
import uuid
|
|
60
61
|
self.subdomain = str(uuid.uuid4())[:8]
|
|
61
62
|
self.server = FastAPI()
|
|
62
|
-
self.
|
|
63
|
+
self.net = net
|
|
63
64
|
self.port = port
|
|
64
65
|
self.url = url
|
|
65
66
|
self.apps = {}
|
|
67
|
+
self.prod = False
|
|
68
|
+
self.email = email
|
|
66
69
|
|
|
67
70
|
def __call__(self, handle):
|
|
68
71
|
def decorator(func):
|
|
@@ -73,13 +76,20 @@ class Cycls:
|
|
|
73
76
|
def sync_wrapper(*args, **kwargs):
|
|
74
77
|
return StreamingResponse(func(*args, **kwargs))
|
|
75
78
|
wrapper = async_wrapper if inspect.iscoroutinefunction(func) else sync_wrapper
|
|
76
|
-
|
|
79
|
+
|
|
80
|
+
if self.url != "": self.prod=True #!
|
|
81
|
+
if not self.prod:
|
|
82
|
+
self.apps[handle + "-dev"] = wrapper
|
|
83
|
+
else:
|
|
84
|
+
self.apps[handle] = wrapper
|
|
85
|
+
|
|
77
86
|
return wrapper
|
|
78
87
|
return decorator
|
|
79
88
|
|
|
80
89
|
async def gateway(self, request: Request):
|
|
81
90
|
data = await request.json()
|
|
82
91
|
handle = data.get('handle')
|
|
92
|
+
print(handle,self.apps)
|
|
83
93
|
if handle in self.apps:
|
|
84
94
|
func = self.apps[handle]
|
|
85
95
|
message = Message(**data)
|
|
@@ -87,37 +97,34 @@ class Cycls:
|
|
|
87
97
|
return {"error": "Handle not found"}
|
|
88
98
|
|
|
89
99
|
def push(self):
|
|
100
|
+
if self.email:
|
|
101
|
+
O("email",self.email)
|
|
102
|
+
O("port",self.port)
|
|
103
|
+
if self.prod:
|
|
104
|
+
O("mode",f"production @ {self.url}")
|
|
105
|
+
register(list(self.apps.keys()), self.net, self.url+"/gateway", self.email)
|
|
106
|
+
else:
|
|
107
|
+
self.url = f"http://{self.subdomain}-cycls.tuns.sh"
|
|
108
|
+
O("mode","development")
|
|
109
|
+
O("docs","for more information, visit https://github.com/Cycls/cycls-py")
|
|
110
|
+
register(list(self.apps.keys()), self.net, self.url+"/gateway", self.email)
|
|
111
|
+
|
|
90
112
|
self.server.post("/gateway")(self.gateway)
|
|
91
113
|
@self.server.on_event("startup")
|
|
92
114
|
def startup_event():
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
115
|
+
if self.prod:
|
|
116
|
+
pass
|
|
117
|
+
else:
|
|
118
|
+
asyncio.create_task(create_ssh_tunnel(f"{self.subdomain}-cycls", self.port))
|
|
97
119
|
try:
|
|
98
120
|
uvicorn.run(self.server, host="127.0.0.1", port=self.port, log_level="error")
|
|
99
121
|
except KeyboardInterrupt:
|
|
100
122
|
print(" ");O("exit","done")
|
|
101
123
|
|
|
102
|
-
def publish(self):
|
|
103
|
-
#!
|
|
104
|
-
prod=False
|
|
105
|
-
if self.url != "":
|
|
106
|
-
prod=True
|
|
107
|
-
|
|
108
|
-
O("port",self.port)
|
|
109
|
-
if prod:
|
|
110
|
-
O("mode",f"production (url:{self.url})")
|
|
111
|
-
register(list(self.apps.keys()), self.graph, self.url+"/gateway", "prod")
|
|
112
|
-
else:
|
|
113
|
-
self.url = f"http://{self.subdomain}-cycls.tuns.sh"
|
|
114
|
-
O("mode","development")
|
|
115
|
-
register(list(self.apps.keys()), self.graph, self.url+"/gateway", "dev")
|
|
116
|
-
|
|
117
124
|
async def call(self, handle, content):
|
|
118
125
|
data = {"handle":handle, "content":content, "session":{}, "agent":"yes"}
|
|
119
126
|
try:
|
|
120
|
-
url = f"{self.
|
|
127
|
+
url = f"{self.net}/stream/"
|
|
121
128
|
async with httpx.AsyncClient(timeout=20) as client, client.stream("POST", url, json=data) as response:
|
|
122
129
|
if response.status_code != 200:
|
|
123
130
|
print("http error")
|
cycls-0.0.2.20/PKG-INFO
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: cycls
|
|
3
|
-
Version: 0.0.2.20
|
|
4
|
-
Summary: Cycls SDK
|
|
5
|
-
Author: Mohammed Jamal
|
|
6
|
-
Author-email: mj@cycls.com
|
|
7
|
-
Requires-Python: >=3.8,<4.0
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
Requires-Dist: asyncssh (>=2.14.2,<3.0.0)
|
|
15
|
-
Requires-Dist: fastapi (>=0.111.0,<0.112.0)
|
|
16
|
-
Requires-Dist: httpx (>=0.27.0,<0.28.0)
|
|
17
|
-
Description-Content-Type: text/markdown
|
|
18
|
-
|
|
19
|
-
</br></br><p align="center"><img src="https://cycls.com/static/assets/favicon.svg" alt="Cycls"></p></br>
|
|
20
|
-
|
|
21
|
-
<div align="center">
|
|
22
|
-
<a href="https://pypi.org/project/cycls/" target="_blank" rel="noopener noreferrer">
|
|
23
|
-
<img loading="lazy" src="https://img.shields.io/pypi/v/cycls.svg" alt="PyPI" class="img_ev3q" style="display: inline;">
|
|
24
|
-
</a>
|
|
25
|
-
<a href="https://discord.gg/BMnaMatDC7" target="_blank" rel="noopener noreferrer">
|
|
26
|
-
<img loading="lazy" src="https://img.shields.io/discord/1175782747164389466" alt="Discord" class="img_ev3q" style="display: inline;">
|
|
27
|
-
</a>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
</br>
|
|
31
|
-
|
|
32
|
-
```sh
|
|
33
|
-
pip install cycls
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
```py
|
|
37
|
-
from cycls import Cycls
|
|
38
|
-
|
|
39
|
-
cycls = Cycls()
|
|
40
|
-
|
|
41
|
-
# sync app on https://cycls.com/@spark
|
|
42
|
-
@cycls("@spark")
|
|
43
|
-
def spark_app(message):
|
|
44
|
-
print("history", message.history)
|
|
45
|
-
print("session id", message.id)
|
|
46
|
-
return message.content + "from spark"
|
|
47
|
-
|
|
48
|
-
# async app on https://cycls.com/@cake
|
|
49
|
-
@cycls("@cake")
|
|
50
|
-
async def cake_app(message):
|
|
51
|
-
print("history", message.history)
|
|
52
|
-
print("session id", message.id)
|
|
53
|
-
return message.content + "from cake"
|
|
54
|
-
|
|
55
|
-
# publish to https://cycls.com
|
|
56
|
-
cycls.push()
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Return a string. Supports markdown. Supports generators for streaming responses.
|
|
60
|
-
|
|
61
|
-
try it live
|
|
62
|
-
- https://cycls.com/@groq
|
|
63
|
-
- https://cycls.com/@openai
|
|
64
|
-
|
|
65
|
-
code examples
|
|
66
|
-
- https://github.com/Cycls/examples/blob/main/groq.py
|
|
67
|
-
- https://github.com/Cycls/examples/blob/main/openai.py
|
|
68
|
-
|
cycls-0.0.2.20/README.md
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
</br></br><p align="center"><img src="https://cycls.com/static/assets/favicon.svg" alt="Cycls"></p></br>
|
|
2
|
-
|
|
3
|
-
<div align="center">
|
|
4
|
-
<a href="https://pypi.org/project/cycls/" target="_blank" rel="noopener noreferrer">
|
|
5
|
-
<img loading="lazy" src="https://img.shields.io/pypi/v/cycls.svg" alt="PyPI" class="img_ev3q" style="display: inline;">
|
|
6
|
-
</a>
|
|
7
|
-
<a href="https://discord.gg/BMnaMatDC7" target="_blank" rel="noopener noreferrer">
|
|
8
|
-
<img loading="lazy" src="https://img.shields.io/discord/1175782747164389466" alt="Discord" class="img_ev3q" style="display: inline;">
|
|
9
|
-
</a>
|
|
10
|
-
</div>
|
|
11
|
-
|
|
12
|
-
</br>
|
|
13
|
-
|
|
14
|
-
```sh
|
|
15
|
-
pip install cycls
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
```py
|
|
19
|
-
from cycls import Cycls
|
|
20
|
-
|
|
21
|
-
cycls = Cycls()
|
|
22
|
-
|
|
23
|
-
# sync app on https://cycls.com/@spark
|
|
24
|
-
@cycls("@spark")
|
|
25
|
-
def spark_app(message):
|
|
26
|
-
print("history", message.history)
|
|
27
|
-
print("session id", message.id)
|
|
28
|
-
return message.content + "from spark"
|
|
29
|
-
|
|
30
|
-
# async app on https://cycls.com/@cake
|
|
31
|
-
@cycls("@cake")
|
|
32
|
-
async def cake_app(message):
|
|
33
|
-
print("history", message.history)
|
|
34
|
-
print("session id", message.id)
|
|
35
|
-
return message.content + "from cake"
|
|
36
|
-
|
|
37
|
-
# publish to https://cycls.com
|
|
38
|
-
cycls.push()
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Return a string. Supports markdown. Supports generators for streaming responses.
|
|
42
|
-
|
|
43
|
-
try it live
|
|
44
|
-
- https://cycls.com/@groq
|
|
45
|
-
- https://cycls.com/@openai
|
|
46
|
-
|
|
47
|
-
code examples
|
|
48
|
-
- https://github.com/Cycls/examples/blob/main/groq.py
|
|
49
|
-
- https://github.com/Cycls/examples/blob/main/openai.py
|
|
File without changes
|
|
File without changes
|