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.
@@ -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
+
@@ -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(7)} | {y}")
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, graph, url, mode):
45
+ def register(handles, net, url, email):
45
46
  try:
46
47
  with httpx.Client() as client:
47
- response = client.post(f"{graph}/register", json={"handles":handles, "url":url, "mode":mode})
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"{graph}/{i[1]}")
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="", graph="https://cycls.com", port=find_available_port(8001)):
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.graph = graph
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
- self.apps[handle] = wrapper
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
- asyncio.create_task(create_ssh_tunnel(f"{self.subdomain}-cycls", self.port))
94
-
95
- self.publish()
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.graph}/stream/"
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")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "cycls"
3
- version = "0.0.2.20"
3
+ version = "0.0.2.21"
4
4
 
5
5
  packages = [{ include = "cycls" }]
6
6
  description = "Cycls SDK"
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