cycls 0.0.2.90__py3-none-any.whl → 0.0.2.92__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.
@@ -17,7 +17,7 @@
17
17
  rel="stylesheet"
18
18
  href="https://esm.sh/katex@0.16.8/dist/katex.min.css"
19
19
  />
20
- <script type="module" crossorigin src="/assets/index-zAUKbDo6.js"></script>
20
+ <script type="module" crossorigin src="/assets/index-BbLcHBku.js"></script>
21
21
  <link rel="stylesheet" crossorigin href="/assets/index-oGkkm3Z8.css">
22
22
  </head>
23
23
  <body style="overflow-x: hidden">
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
- debug: bool = False
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, debug=False):
41
- import traceback
42
- try:
43
- if inspect.isasyncgen(stream):
44
- async for item in stream:
45
- if msg := sse(item): yield msg
46
- else:
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
- context = Context(messages = Messages(messages), user = User(**user_data) if user_data else None)
131
- try:
132
- stream = await func(context) if inspect.iscoroutinefunction(func) else func(context)
133
- except Exception as e:
134
- error_msg = traceback.format_exc() if config.debug else str(e)
135
- async def error_stream():
136
- yield sse({"type": "thinking", "thinking": f"⚠️ Error\n```\n{error_msg}```"})
137
- yield "data: [DONE]\n\n"
138
- return StreamingResponse(error_stream(), media_type="text/event-stream")
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, debug=config.debug)
150
+ stream = encoder(stream)
143
151
  return StreamingResponse(stream, media_type="text/event-stream")
144
152
 
145
153
  @app.get("/config")
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cycls
3
- Version: 0.0.2.90
3
+ Version: 0.0.2.92
4
4
  Summary: Distribute Intelligence
5
5
  Author-email: "Mohammed J. AlRujayi" <mj@cycls.com>
6
- Requires-Python: >=3.9
6
+ Requires-Python: >=3.10
7
7
  Requires-Dist: cloudpickle>=3.1.1
8
8
  Requires-Dist: docker>=7.1.0
9
9
  Requires-Dist: email-validator>=2.0.0
@@ -11,6 +11,9 @@ Requires-Dist: fastapi>=0.111.0
11
11
  Requires-Dist: httpx>=0.27.0
12
12
  Requires-Dist: pyjwt>=2.8.0
13
13
  Requires-Dist: uvicorn>=0.30.0
14
+ Requires-Dist: watchfiles>=1.0.0
15
+ Provides-Extra: state
16
+ Requires-Dist: agentfs-sdk==0.4.0; extra == 'state'
14
17
  Description-Content-Type: text/markdown
15
18
 
16
19
  <h3 align="center">
@@ -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.92.dist-info/METADATA,sha256=7ZmdYeooaN0AfBRUpsPU-xMz8syrHIuzpoAO-sOVfzc,8869
13
+ cycls-0.0.2.92.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
+ cycls-0.0.2.92.dist-info/entry_points.txt,sha256=CktT5eNvW_Qxomf7L_Ez_GdUbL6qAfx_Utm6_HtUJwE,41
15
+ cycls-0.0.2.92.dist-info/RECORD,,