cycls 0.0.2.48__py3-none-any.whl → 0.0.2.50__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/runtime.py CHANGED
@@ -386,7 +386,7 @@ COPY {self.payload_file} {self.io_dir}/
386
386
  data=data_payload,
387
387
  files=files,
388
388
  headers=headers,
389
- timeout=1800 # Set a long timeout for the entire process
389
+ timeout=5*1800 # Set a long timeout for the entire process
390
390
  )
391
391
 
392
392
  # 4. Handle the server's response
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
- theme_path = importlib.resources.files('cycls').joinpath('theme')
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, api_key=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, api_key)
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=theme_path, org=None, api_token=None, pip=[], apt=[], copy=[], copy_public=[], keys=["",""], api_key=None):
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.keys, self.pip, self.apt, self.copy, self.copy_public = keys, pip, apt, copy, copy_public
25
- self.api_key = api_key
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.api_key is None) and prod:
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(cycls_path)+"/web.py":"web.py"}
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 runner(port):
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🚀 Local Link: http://localhost:{port}\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=runner,
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
- api_key=self.api_key
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.keys)
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(cycls_path)+"/web.py", "/root/web.py"))
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}')
@@ -128,5 +128,5 @@ class Agent:
128
128
 
129
129
  # docker system prune -af
130
130
  # poetry config pypi-token.pypi <your-token>
131
- # poetry run python agent-deploy.py
131
+ # poetry run python cake.py
132
132
  # poetry publish --build
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cycls
3
- Version: 0.0.2.48
3
+ Version: 0.0.2.50
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 a zero-config framework 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.
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 "hi"
78
+ yield "Hello, World!"
85
79
 
86
- agent.local()
80
+ agent.deploy(prod=False)
87
81
  ```
88
82
 
89
83
  Run it from your terminal:
@@ -97,20 +91,19 @@ This will start a local server. Open your browser to http://localhost:8080 to in
97
91
  This example creates a more advanced agent that calls the OpenAI API. It will be deployed to the cloud with authentication enabled.
98
92
 
99
93
  ```py
100
- # deploy.py
101
94
  import cycls
102
95
 
103
96
  # Initialize the agent with dependencies and API keys
104
97
  agent = cycls.Agent(
105
98
  pip=["openai"],
106
- keys=["ak-<token_id>", "as-<token_secret>"]
99
+ key="YOUR_CYCLS_KEY" # Get yours from https://cycls.com
107
100
  )
108
101
 
109
102
  # A helper function to call the LLM
110
103
  async def llm(messages):
111
- # Import inside the function: 'openai' is only needed at runtime in the container.
104
+ # Import inside the function: 'openai' is needed at runtime in the container.
112
105
  import openai
113
- client = openai.AsyncOpenAI(api_key="sk-...") # Your OpenAI key
106
+ client = openai.AsyncOpenAI(api_key="YOUR_OPENAI_API_KEY")
114
107
  model = "gpt-4o"
115
108
  response = await client.chat.completions.create(
116
109
  model=model,
@@ -1,9 +1,9 @@
1
1
  cycls/__init__.py,sha256=bVT0dYTXLdSC3ZURgtm-DEOj-VO6RUM6zGsJB0zuj6Y,61
2
- cycls/runtime.py,sha256=GoRfyPn2uKTIMb4FSowjfo02DsL0VrunDuybdeZxsvM,18221
3
- cycls/sdk.py,sha256=dGcuOrVdjL0epsxyMUappNUC-cfFW0G1ibT8xtCcFVk,5844
2
+ cycls/runtime.py,sha256=hLBtwtGz0FCW1-EPCJy6kMdF2fB3i6Df_H8-bm7qeK0,18223
3
+ cycls/sdk.py,sha256=jdgQDIQ1YP1y725bYYs6NRsA5UGor7Sso59BTcdBY1w,5869
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.48.dist-info/METADATA,sha256=t8TLrWO0TDs7z-yrQdWXPYlGHVp_S9Qcsv2MYTgvras,5673
8
- cycls-0.0.2.48.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
9
- cycls-0.0.2.48.dist-info/RECORD,,
7
+ cycls-0.0.2.50.dist-info/METADATA,sha256=IdbN2LxpZVv15FxZaOUl-N9otz_CQ7IDZ6zRtaxPwo0,4800
8
+ cycls-0.0.2.50.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
9
+ cycls-0.0.2.50.dist-info/RECORD,,