jvserve 2.0.11__py3-none-any.whl → 2.0.13__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.

Potentially problematic release.


This version of jvserve might be problematic. Click here for more details.

jvserve/__init__.py CHANGED
@@ -4,5 +4,5 @@ jvserve package initialization.
4
4
  This package provides the webserver for loading and interacting with JIVAS agents.
5
5
  """
6
6
 
7
- __version__ = "2.0.11"
7
+ __version__ = "2.0.13"
8
8
  __supported__jivas__versions__ = ["2.0.0"]
jvserve/cli.py CHANGED
@@ -7,14 +7,13 @@ from contextlib import asynccontextmanager
7
7
  from typing import AsyncIterator, Optional
8
8
 
9
9
  from dotenv import load_dotenv
10
- from fastapi.responses import FileResponse, StreamingResponse
10
+ from fastapi.responses import FileResponse, Response, StreamingResponse
11
11
  from jac_cloud.jaseci.security import authenticator
12
12
  from jac_cloud.plugin.jaseci import NodeAnchor
13
13
  from jaclang.cli.cmdreg import cmd_registry
14
14
  from jaclang.plugin.default import hookimpl
15
15
  from jaclang.runtimelib.context import ExecutionContext
16
16
  from jaclang.runtimelib.machine import JacMachine
17
- from requests import Response
18
17
  from uvicorn import run as _run
19
18
 
20
19
  from jvserve.lib.agent_interface import AgentInterface
@@ -176,7 +175,7 @@ class JacCmd:
176
175
  def jvfileserve(
177
176
  directory: str, host: str = "0.0.0.0", port: int = 9000
178
177
  ) -> None:
179
- """Launch the file server."""
178
+ """Launch the file server for local files."""
180
179
  # load FastAPI
181
180
  from fastapi import FastAPI
182
181
  from fastapi.middleware.cors import CORSMiddleware
@@ -194,33 +193,60 @@ class JacCmd:
194
193
  allow_headers=["*"],
195
194
  )
196
195
 
197
- if FILE_INTERFACE == "local":
198
- if directory:
199
- os.environ["JIVAS_FILES_ROOT_PATH"] = directory
196
+ if not os.path.exists(directory):
197
+ os.makedirs(directory)
200
198
 
201
- if not os.path.exists(directory):
202
- os.makedirs(directory)
199
+ # Set the environment variable for the file root path
200
+ os.environ["JIVAS_FILES_ROOT_PATH"] = directory
203
201
 
204
- app.mount(
205
- "/files",
206
- StaticFiles(
207
- directory=os.environ.get("JIVAS_FILES_ROOT_PATH", ".files")
208
- ),
209
- name="files",
210
- )
202
+ # Mount the static files directory
203
+ app.mount(
204
+ "/files",
205
+ StaticFiles(directory=directory),
206
+ name="files",
207
+ )
208
+
209
+ # run the app
210
+ _run(app, host=host, port=port)
211
+
212
+ @cmd_registry.register
213
+ def jvproxyserve(
214
+ directory: str, host: str = "0.0.0.0", port: int = 9000
215
+ ) -> None:
216
+ """Launch the file proxy server for remote files."""
217
+ # load FastAPI
218
+ from fastapi import FastAPI
219
+ from fastapi.middleware.cors import CORSMiddleware
220
+
221
+ # Setup custom routes
222
+ app = FastAPI()
211
223
 
224
+ # Add CORS middleware
225
+ app.add_middleware(
226
+ CORSMiddleware,
227
+ allow_origins=["*"],
228
+ allow_credentials=True,
229
+ allow_methods=["*"],
230
+ allow_headers=["*"],
231
+ )
232
+
233
+ # Add proxy routes only if using S3
212
234
  if FILE_INTERFACE == "s3":
213
235
 
214
236
  @app.get("/files/{file_path:path}", response_model=None)
215
237
  async def serve_file(
216
238
  file_path: str,
217
- ) -> Response:
239
+ ) -> FileResponse | StreamingResponse | Response:
240
+ descriptor_path = os.environ["JIVAS_DESCRIPTOR_ROOT_PATH"]
241
+ if descriptor_path and descriptor_path in file_path:
242
+ return Response(status_code=403)
243
+
218
244
  return serve_proxied_file(file_path)
219
245
 
220
246
  @app.get("/f/{file_id:path}", response_model=None)
221
247
  async def get_proxied_file(
222
248
  file_id: str,
223
- ) -> Response:
249
+ ) -> FileResponse | StreamingResponse | Response:
224
250
  from bson import ObjectId
225
251
  from fastapi import HTTPException
226
252
 
@@ -230,8 +256,12 @@ class JacCmd:
230
256
  # mongo db collection
231
257
  collection = NodeAnchor.Collection.get_collection("url_proxies")
232
258
  file_details = collection.find_one({"_id": ObjectId(object_id)})
259
+ descriptor_path = os.environ["JIVAS_DESCRIPTOR_ROOT_PATH"]
233
260
 
234
261
  if file_details:
262
+ if descriptor_path and descriptor_path in file_details["path"]:
263
+ return Response(status_code=403)
264
+
235
265
  return serve_proxied_file(file_details["path"])
236
266
 
237
267
  raise HTTPException(status_code=404, detail="File not found")
@@ -1,5 +1,6 @@
1
1
  """Agent Interface class and methods for interaction with Jivas."""
2
2
 
3
+ import asyncio
3
4
  import json
4
5
  import logging
5
6
  import os
@@ -243,7 +244,7 @@ class AgentInterface:
243
244
  streaming: Optional[bool] = None
244
245
 
245
246
  @staticmethod
246
- def interact(payload: InteractPayload) -> dict:
247
+ def interact(payload: InteractPayload, request: Request) -> dict:
247
248
  """Interact with the agent."""
248
249
  response = None
249
250
  ctx = AgentInterface.load_context()
@@ -291,7 +292,7 @@ class AgentInterface:
291
292
  interaction_node = response.interaction_node
292
293
 
293
294
  async def generate(
294
- generator: Iterator,
295
+ generator: Iterator, request: Request
295
296
  ) -> AsyncGenerator[str, None]:
296
297
  """
297
298
  Asynchronously yield data chunks from a response generator in Server-Sent Events (SSE) format.
@@ -304,11 +305,11 @@ class AgentInterface:
304
305
  """
305
306
  full_text = ""
306
307
  total_tokens = 0
308
+
307
309
  try:
308
310
  for chunk in generator:
309
311
  full_text += chunk.content
310
312
  total_tokens += 1 # each chunk is a token, let's tally
311
- await sleep(0.025)
312
313
  yield (
313
314
  "data: "
314
315
  + json.dumps(
@@ -324,6 +325,7 @@ class AgentInterface:
324
325
  )
325
326
  + "\n\n"
326
327
  )
328
+ await sleep(0.025)
327
329
  # Update the interaction node with the fully generated text
328
330
  actx = await AgentInterface.load_context_async()
329
331
  try:
@@ -336,7 +338,7 @@ class AgentInterface:
336
338
  attributes={
337
339
  "interaction_data": interaction_node.export(),
338
340
  },
339
- module_name="jivas.agent.action.update_interaction",
341
+ module_name="jivas.agent.memory.update_interaction",
340
342
  ),
341
343
  )
342
344
  finally:
@@ -347,9 +349,30 @@ class AgentInterface:
347
349
  AgentInterface.LOGGER.error(
348
350
  f"Exception in streaming generator: {e}, {traceback.format_exc()}"
349
351
  )
352
+ except asyncio.CancelledError:
353
+ AgentInterface.LOGGER.error(
354
+ "Client disconnected. Aborting stream."
355
+ )
356
+ actx = await AgentInterface.load_context_async()
357
+ try:
358
+ interaction_node.set_text_message(message=full_text)
359
+ interaction_node.add_tokens(total_tokens)
360
+ _Jac.spawn_call(
361
+ NodeAnchor.ref(interaction_node.id).architype,
362
+ AgentInterface.spawn_walker(
363
+ walker_name="update_interaction",
364
+ attributes={
365
+ "interaction_data": interaction_node.export(),
366
+ },
367
+ module_name="jivas.agent.memory.update_interaction",
368
+ ),
369
+ )
370
+ finally:
371
+ if actx:
372
+ actx.close()
350
373
 
351
374
  return StreamingResponse(
352
- generate(response.generator),
375
+ generate(response.generator, request),
353
376
  media_type="text/event-stream",
354
377
  )
355
378
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jvserve
3
- Version: 2.0.11
3
+ Version: 2.0.13
4
4
  Summary: FastAPI webserver for loading and interaction with JIVAS agents.
5
5
  Home-page: https://github.com/TrueSelph/jvserve
6
6
  Author: TrueSelph Inc.
@@ -0,0 +1,13 @@
1
+ jvserve/__init__.py,sha256=AHR-iejuKB2C8u25HZ1ccXlh6tCaB3MuKVTJz-LZzig,191
2
+ jvserve/cli.py,sha256=NJD4ehtKnhOvsz-vrFh9lz3P4bnxqz-uqTr8QItljZc,8897
3
+ jvserve/lib/__init__.py,sha256=cnzfSHLoTWG9Ygut2nOpDys5aPlQz-m0BSkB-nd7OMs,31
4
+ jvserve/lib/agent_interface.py,sha256=4SHqvySxu08dK2cPoe2TjMKlm11VqM0qDalOKp-tma4,32347
5
+ jvserve/lib/agent_pulse.py,sha256=6hBF6KQYr6Z9Mi_yoWKGfdnW7gg84kK20Slu-bLR_m8,2067
6
+ jvserve/lib/file_interface.py,sha256=sqwTmBnZsVFQUGt7mE1EWA-jHnZlRtBAFeb4Rb_QgQ8,6079
7
+ jvserve/lib/jvlogger.py,sha256=RNiB9PHuBzTvNIQWhxoDgrDlNYA0PYm1SVpvzlqu8mE,4180
8
+ jvserve-2.0.13.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
9
+ jvserve-2.0.13.dist-info/METADATA,sha256=8gyJ1EnRbjZDZnOU3F-Y4lq9loXHIGLNCXn3YpPiUzg,4791
10
+ jvserve-2.0.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
+ jvserve-2.0.13.dist-info/entry_points.txt,sha256=HYyg1QXoLs0JRb004L300VeLOZyDLY27ynD1tnTnEN4,35
12
+ jvserve-2.0.13.dist-info/top_level.txt,sha256=afoCXZv-zXNBuhVIvfJGjafXKEiJl_ooy4BtgQwAG4Q,8
13
+ jvserve-2.0.13.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.7.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,13 +0,0 @@
1
- jvserve/__init__.py,sha256=sJ_mBKN30rjktWYox9bigWcSsNjhSIbEq-EWFvhYAAc,191
2
- jvserve/cli.py,sha256=ptbu2_u6fZHXyIPPYRt5xKJL_l0OVhq8hETGkAGuvqk,7699
3
- jvserve/lib/__init__.py,sha256=cnzfSHLoTWG9Ygut2nOpDys5aPlQz-m0BSkB-nd7OMs,31
4
- jvserve/lib/agent_interface.py,sha256=vGJQ9A_9kWfa6YoW7BiidZO6Huf-0XSlunMLMNGqgws,31053
5
- jvserve/lib/agent_pulse.py,sha256=6hBF6KQYr6Z9Mi_yoWKGfdnW7gg84kK20Slu-bLR_m8,2067
6
- jvserve/lib/file_interface.py,sha256=sqwTmBnZsVFQUGt7mE1EWA-jHnZlRtBAFeb4Rb_QgQ8,6079
7
- jvserve/lib/jvlogger.py,sha256=RNiB9PHuBzTvNIQWhxoDgrDlNYA0PYm1SVpvzlqu8mE,4180
8
- jvserve-2.0.11.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
9
- jvserve-2.0.11.dist-info/METADATA,sha256=avBB2xIYh266s2UxgR9MF3hVK4dUzWBxgYPJr0Fn2qc,4791
10
- jvserve-2.0.11.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
11
- jvserve-2.0.11.dist-info/entry_points.txt,sha256=HYyg1QXoLs0JRb004L300VeLOZyDLY27ynD1tnTnEN4,35
12
- jvserve-2.0.11.dist-info/top_level.txt,sha256=afoCXZv-zXNBuhVIvfJGjafXKEiJl_ooy4BtgQwAG4Q,8
13
- jvserve-2.0.11.dist-info/RECORD,,