cycls 0.0.2.48__py3-none-any.whl → 0.0.2.49__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/sdk.py
CHANGED
|
@@ -4,25 +4,24 @@ from modal.runner import run_app
|
|
|
4
4
|
from .web import web
|
|
5
5
|
import importlib.resources
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
cycls_path = importlib.resources.files('cycls')
|
|
7
|
+
CYCLS_PATH = importlib.resources.files('cycls')
|
|
9
8
|
|
|
10
|
-
def function(python_version=None, pip=None, apt=None, run_commands=None, copy=None, name=None, base_url=None,
|
|
9
|
+
def function(python_version=None, pip=None, apt=None, run_commands=None, copy=None, name=None, base_url=None, key=None):
|
|
11
10
|
# """
|
|
12
11
|
# A decorator factory that transforms a Python function into a containerized,
|
|
13
12
|
# remotely executable object.
|
|
14
13
|
def decorator(func):
|
|
15
14
|
Name = name or func.__name__
|
|
16
15
|
copy_dict = {i:i for i in copy or []}
|
|
17
|
-
return Runtime(func, Name.replace('_', '-'), python_version, pip, apt, run_commands, copy_dict, base_url,
|
|
16
|
+
return Runtime(func, Name.replace('_', '-'), python_version, pip, apt, run_commands, copy_dict, base_url, key)
|
|
18
17
|
return decorator
|
|
19
18
|
|
|
20
19
|
class Agent:
|
|
21
|
-
def __init__(self, theme=
|
|
20
|
+
def __init__(self, theme=CYCLS_PATH.joinpath('theme'), org=None, api_token=None, pip=[], apt=[], copy=[], copy_public=[], modal_keys=["",""], key=None, base_url=None):
|
|
22
21
|
self.org, self.api_token = org, api_token
|
|
23
22
|
self.theme = theme
|
|
24
|
-
self.
|
|
25
|
-
self.
|
|
23
|
+
self.key, self.modal_keys, self.pip, self.apt, self.copy, self.copy_public = key, modal_keys, pip, apt, copy, copy_public
|
|
24
|
+
self.base_url = base_url
|
|
26
25
|
|
|
27
26
|
self.registered_functions = []
|
|
28
27
|
|
|
@@ -55,7 +54,7 @@ class Agent:
|
|
|
55
54
|
if not self.registered_functions:
|
|
56
55
|
print("Error: No @agent decorated function found.")
|
|
57
56
|
return
|
|
58
|
-
if (self.
|
|
57
|
+
if (self.key is None) and prod:
|
|
59
58
|
print("🛑 Error: Please add your Cycls API key")
|
|
60
59
|
return
|
|
61
60
|
|
|
@@ -65,36 +64,37 @@ class Agent:
|
|
|
65
64
|
|
|
66
65
|
i["config"][1] = False
|
|
67
66
|
|
|
68
|
-
copy={str(self.theme):"theme", str(
|
|
67
|
+
copy={str(self.theme):"theme", str(CYCLS_PATH)+"/web.py":"web.py"}
|
|
69
68
|
copy.update({i:i for i in self.copy})
|
|
70
69
|
copy.update({i:f"public/{i}" for i in self.copy_public})
|
|
71
70
|
|
|
72
|
-
def
|
|
71
|
+
def server(port):
|
|
73
72
|
import uvicorn, logging
|
|
74
73
|
# This one-liner hides the confusing "0.0.0.0" message
|
|
75
74
|
logging.getLogger("uvicorn.error").addFilter(type("F",(),{"filter": lambda s,r: "0.0.0.0" not in r.getMessage()})())
|
|
76
|
-
print(f"\n
|
|
75
|
+
print(f"\n🔨 Visit {i["name"]} => http://localhost:{port}\n")
|
|
77
76
|
uvicorn.run(__import__("web").web(i["func"], *i["config"]), host="0.0.0.0", port=port)
|
|
78
77
|
|
|
79
78
|
new = Runtime(
|
|
80
79
|
# func=lambda port: __import__("uvicorn").run(__import__("web").web(i["func"], *i["config"]), host="0.0.0.0", port=port),
|
|
81
|
-
func=
|
|
80
|
+
func=server,
|
|
82
81
|
name=i["name"],
|
|
83
82
|
apt_packages=self.apt,
|
|
84
83
|
pip_packages=["fastapi[standard]", "pyjwt", "cryptography", "uvicorn", *self.pip],
|
|
85
84
|
copy=copy,
|
|
86
|
-
|
|
85
|
+
base_url=self.base_url,
|
|
86
|
+
api_key=self.key
|
|
87
87
|
)
|
|
88
88
|
new.deploy(port=port) if prod else new.run(port=port)
|
|
89
89
|
return
|
|
90
90
|
|
|
91
91
|
def modal(self, prod=False):
|
|
92
|
-
self.client = modal.Client.from_credentials(*self.
|
|
92
|
+
self.client = modal.Client.from_credentials(*self.modal_keys)
|
|
93
93
|
image = (modal.Image.debian_slim()
|
|
94
94
|
.pip_install("fastapi[standard]", "pyjwt", "cryptography", *self.pip)
|
|
95
95
|
.apt_install(*self.apt)
|
|
96
96
|
.add_local_dir(self.theme, "/root/theme")
|
|
97
|
-
.add_local_file(str(
|
|
97
|
+
.add_local_file(str(CYCLS_PATH)+"/web.py", "/root/web.py"))
|
|
98
98
|
|
|
99
99
|
for item in self.copy:
|
|
100
100
|
image = image.add_local_file(item, f"/root/{item}") if "." in item else image.add_local_dir(item, f'/root/{item}')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cycls
|
|
3
|
-
Version: 0.0.2.
|
|
3
|
+
Version: 0.0.2.49
|
|
4
4
|
Summary: Cycls SDK
|
|
5
5
|
Author: Mohammed J. AlRujayi
|
|
6
6
|
Author-email: mj@cycls.com
|
|
@@ -40,15 +40,7 @@ The Distribution SDK for AI Agents.
|
|
|
40
40
|
|
|
41
41
|
# Cycls 🚲
|
|
42
42
|
|
|
43
|
-
`cycls` is
|
|
44
|
-
|
|
45
|
-
### Design Philosophy
|
|
46
|
-
`cycls` is an anti-framework. We treat the boilerplate, config files, and infrastructure that surround modern applications as a bug to be eliminated. A developer's focus is the most valuable resource, and context-switching is its greatest enemy.
|
|
47
|
-
|
|
48
|
-
Our zero-config approach makes your Python script the single source of truth for the entire application. When your code is all you need, you stay focused, iterate faster, and ship with confidence.
|
|
49
|
-
|
|
50
|
-
This philosophy has a powerful side-effect: it makes development genuinely iterative. The self-contained nature of an agent encourages you to 'build in cycles'—starting simple and adding complexity without penalty. This same simplicity also makes `cycls` an ideal target for code generation. Because the entire application can be expressed in one file, LLMs can write, modify, and reason about `cycls` agents far more effectively than with traditional frameworks. It's a seamless interface for both human and machine.
|
|
51
|
-
|
|
43
|
+
`cycls` is an open-source SDK for building and publishing AI agents. With a single decorator and one command, you can deploy your code as a web application complete with a front-end UI and an OpenAI-compatible API endpoint.
|
|
52
44
|
|
|
53
45
|
## Key Features
|
|
54
46
|
|
|
@@ -67,6 +59,8 @@ This philosophy has a powerful side-effect: it makes development genuinely itera
|
|
|
67
59
|
pip install cycls
|
|
68
60
|
```
|
|
69
61
|
|
|
62
|
+
**Note:** You must have [Docker](https://www.docker.com/get-started) installed and running on your machine.
|
|
63
|
+
|
|
70
64
|
## How to Use
|
|
71
65
|
### 1. Local Development: "Hello, World!"
|
|
72
66
|
|
|
@@ -81,9 +75,9 @@ agent = cycls.Agent()
|
|
|
81
75
|
# Decorate your function to register it as an agent
|
|
82
76
|
@agent()
|
|
83
77
|
async def hello(context):
|
|
84
|
-
yield "
|
|
78
|
+
yield "Hello, World!"
|
|
85
79
|
|
|
86
|
-
agent.
|
|
80
|
+
agent.deploy(prod=False)
|
|
87
81
|
```
|
|
88
82
|
|
|
89
83
|
Run it from your terminal:
|
|
@@ -103,12 +97,12 @@ import cycls
|
|
|
103
97
|
# Initialize the agent with dependencies and API keys
|
|
104
98
|
agent = cycls.Agent(
|
|
105
99
|
pip=["openai"],
|
|
106
|
-
|
|
100
|
+
key=["YOUR_CYCLS_KEY"] # Get yours from cycls.com
|
|
107
101
|
)
|
|
108
102
|
|
|
109
103
|
# A helper function to call the LLM
|
|
110
104
|
async def llm(messages):
|
|
111
|
-
# Import inside the function: 'openai' is
|
|
105
|
+
# Import inside the function: 'openai' is needed at runtime in the container.
|
|
112
106
|
import openai
|
|
113
107
|
client = openai.AsyncOpenAI(api_key="sk-...") # Your OpenAI key
|
|
114
108
|
model = "gpt-4o"
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
cycls/__init__.py,sha256=bVT0dYTXLdSC3ZURgtm-DEOj-VO6RUM6zGsJB0zuj6Y,61
|
|
2
2
|
cycls/runtime.py,sha256=GoRfyPn2uKTIMb4FSowjfo02DsL0VrunDuybdeZxsvM,18221
|
|
3
|
-
cycls/sdk.py,sha256=
|
|
3
|
+
cycls/sdk.py,sha256=6_kBpLhksvuFkk1H1vDV--36RMujmpqJ-7LpYzFEPuw,5877
|
|
4
4
|
cycls/theme/assets/index-CJ_4y8Hq.js,sha256=5D1ALXOnkyWH3KkmJ4DeYLzlN4JONL1xg3cCgUVyvLA,1103624
|
|
5
5
|
cycls/theme/index.html,sha256=GGoeZQYDvZpkqby9gxMK7XgCazsmJtJ5M4fDJE8IhwU,664
|
|
6
6
|
cycls/web.py,sha256=oc1a-Z3dFy4Ub7u0wF5_wrsvoosT3NgrOw4iWJ5KFns,4979
|
|
7
|
-
cycls-0.0.2.
|
|
8
|
-
cycls-0.0.2.
|
|
9
|
-
cycls-0.0.2.
|
|
7
|
+
cycls-0.0.2.49.dist-info/METADATA,sha256=Vvu9PfvGW8GdDbYV9vTsiKrh5KcZIfE7BNB-nBS5CwY,4811
|
|
8
|
+
cycls-0.0.2.49.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
9
|
+
cycls-0.0.2.49.dist-info/RECORD,,
|
|
File without changes
|