jvserve 2.0.12__tar.gz → 2.0.13__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.
Potentially problematic release.
This version of jvserve might be problematic. Click here for more details.
- {jvserve-2.0.12 → jvserve-2.0.13}/PKG-INFO +1 -1
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve/__init__.py +1 -1
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve/cli.py +15 -6
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve/lib/agent_interface.py +28 -5
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve.egg-info/PKG-INFO +1 -1
- {jvserve-2.0.12 → jvserve-2.0.13}/LICENSE +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/README.md +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve/lib/__init__.py +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve/lib/agent_pulse.py +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve/lib/file_interface.py +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve/lib/jvlogger.py +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve.egg-info/SOURCES.txt +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve.egg-info/dependency_links.txt +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve.egg-info/entry_points.txt +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve.egg-info/requires.txt +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/jvserve.egg-info/top_level.txt +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/setup.cfg +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/setup.py +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/tests/test_file_interface.py +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/tests/test_jvlogger.py +0 -0
- {jvserve-2.0.12 → jvserve-2.0.13}/tests/test_jvserve.py +0 -0
|
@@ -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
|
|
@@ -216,8 +215,7 @@ class JacCmd:
|
|
|
216
215
|
) -> None:
|
|
217
216
|
"""Launch the file proxy server for remote files."""
|
|
218
217
|
# load FastAPI
|
|
219
|
-
from
|
|
220
|
-
from fastapi import FastAPI, HTTPException
|
|
218
|
+
from fastapi import FastAPI
|
|
221
219
|
from fastapi.middleware.cors import CORSMiddleware
|
|
222
220
|
|
|
223
221
|
# Setup custom routes
|
|
@@ -238,21 +236,32 @@ class JacCmd:
|
|
|
238
236
|
@app.get("/files/{file_path:path}", response_model=None)
|
|
239
237
|
async def serve_file(
|
|
240
238
|
file_path: str,
|
|
241
|
-
) -> 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
|
+
|
|
242
244
|
return serve_proxied_file(file_path)
|
|
243
245
|
|
|
244
246
|
@app.get("/f/{file_id:path}", response_model=None)
|
|
245
247
|
async def get_proxied_file(
|
|
246
248
|
file_id: str,
|
|
247
|
-
) -> Response:
|
|
249
|
+
) -> FileResponse | StreamingResponse | Response:
|
|
250
|
+
from bson import ObjectId
|
|
251
|
+
from fastapi import HTTPException
|
|
252
|
+
|
|
248
253
|
params = file_id.split("/")
|
|
249
254
|
object_id = params[0]
|
|
250
255
|
|
|
251
256
|
# mongo db collection
|
|
252
257
|
collection = NodeAnchor.Collection.get_collection("url_proxies")
|
|
253
258
|
file_details = collection.find_one({"_id": ObjectId(object_id)})
|
|
259
|
+
descriptor_path = os.environ["JIVAS_DESCRIPTOR_ROOT_PATH"]
|
|
254
260
|
|
|
255
261
|
if file_details:
|
|
262
|
+
if descriptor_path and descriptor_path in file_details["path"]:
|
|
263
|
+
return Response(status_code=403)
|
|
264
|
+
|
|
256
265
|
return serve_proxied_file(file_details["path"])
|
|
257
266
|
|
|
258
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.
|
|
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
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|