jvserve 2.0.8__py3-none-any.whl → 2.0.10__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 +1 -1
- jvserve/lib/agent_interface.py +96 -7
- {jvserve-2.0.8.dist-info → jvserve-2.0.10.dist-info}/METADATA +1 -1
- jvserve-2.0.10.dist-info/RECORD +13 -0
- {jvserve-2.0.8.dist-info → jvserve-2.0.10.dist-info}/WHEEL +1 -1
- jvserve-2.0.8.dist-info/RECORD +0 -13
- {jvserve-2.0.8.dist-info → jvserve-2.0.10.dist-info}/entry_points.txt +0 -0
- {jvserve-2.0.8.dist-info → jvserve-2.0.10.dist-info}/licenses/LICENSE +0 -0
- {jvserve-2.0.8.dist-info → jvserve-2.0.10.dist-info}/top_level.txt +0 -0
jvserve/__init__.py
CHANGED
jvserve/lib/agent_interface.py
CHANGED
|
@@ -6,13 +6,14 @@ import os
|
|
|
6
6
|
import string
|
|
7
7
|
import time
|
|
8
8
|
import traceback
|
|
9
|
-
from
|
|
9
|
+
from asyncio import sleep
|
|
10
|
+
from typing import Any, AsyncGenerator, Dict, Iterator, List, Optional
|
|
10
11
|
from urllib.parse import quote, unquote
|
|
11
12
|
|
|
12
13
|
import aiohttp
|
|
13
14
|
import requests
|
|
14
15
|
from fastapi import File, Form, Request, UploadFile
|
|
15
|
-
from fastapi.responses import JSONResponse
|
|
16
|
+
from fastapi.responses import JSONResponse, StreamingResponse
|
|
16
17
|
from jac_cloud.core.architype import AnchorState, Permission, Root
|
|
17
18
|
from jac_cloud.core.context import (
|
|
18
19
|
JASECI_CONTEXT,
|
|
@@ -129,6 +130,7 @@ class AgentInterface:
|
|
|
129
130
|
AgentInterface.spawn_walker(
|
|
130
131
|
walker_name=walker,
|
|
131
132
|
attributes={
|
|
133
|
+
"headers": request.headers,
|
|
132
134
|
"agent_id": agent_id,
|
|
133
135
|
"params": params,
|
|
134
136
|
"reporting": False,
|
|
@@ -243,7 +245,6 @@ class AgentInterface:
|
|
|
243
245
|
@staticmethod
|
|
244
246
|
def interact(payload: InteractPayload) -> dict:
|
|
245
247
|
"""Interact with the agent."""
|
|
246
|
-
|
|
247
248
|
response = None
|
|
248
249
|
ctx = AgentInterface.load_context()
|
|
249
250
|
session_id = payload.session_id if payload.session_id else ""
|
|
@@ -273,15 +274,103 @@ class AgentInterface:
|
|
|
273
274
|
},
|
|
274
275
|
module_name="jivas.agent.action.interact",
|
|
275
276
|
),
|
|
276
|
-
)
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
if payload.streaming:
|
|
280
|
+
# since streaming occurs asynchronously, we'll need to close the context for writebacks here
|
|
281
|
+
# at this point of closure, there will be an open interaction_node without a response
|
|
282
|
+
# our job hereafter is to stream to completion and then update and close this interaction_node with the final result
|
|
283
|
+
|
|
284
|
+
ctx.close()
|
|
285
|
+
if (
|
|
286
|
+
response is not None
|
|
287
|
+
and hasattr(response, "generator")
|
|
288
|
+
and hasattr(response, "interaction_node")
|
|
289
|
+
):
|
|
290
|
+
|
|
291
|
+
interaction_node = response.interaction_node
|
|
292
|
+
|
|
293
|
+
async def generate(
|
|
294
|
+
generator: Iterator,
|
|
295
|
+
) -> AsyncGenerator[str, None]:
|
|
296
|
+
"""
|
|
297
|
+
Asynchronously yield data chunks from a response generator in Server-Sent Events (SSE) format.
|
|
298
|
+
|
|
299
|
+
Accumulates the full text content and yields each chunk as a JSON-encoded SSE message.
|
|
300
|
+
After all chunks are processed, updates the interaction node with the complete generated text and triggers an update in the graph context.
|
|
301
|
+
|
|
302
|
+
Yields:
|
|
303
|
+
str: A JSON-encoded string representing the current chunk of data in SSE format.
|
|
304
|
+
"""
|
|
305
|
+
full_text = ""
|
|
306
|
+
total_tokens = 0
|
|
307
|
+
try:
|
|
308
|
+
for chunk in generator:
|
|
309
|
+
full_text += chunk.content
|
|
310
|
+
total_tokens += 1 # each chunk is a token, let's tally
|
|
311
|
+
await sleep(0.025)
|
|
312
|
+
yield (
|
|
313
|
+
"data: "
|
|
314
|
+
+ json.dumps(
|
|
315
|
+
{
|
|
316
|
+
"id": interaction_node.id,
|
|
317
|
+
"content": chunk.content,
|
|
318
|
+
"session_id": interaction_node.response.get(
|
|
319
|
+
"session_id"
|
|
320
|
+
),
|
|
321
|
+
"type": chunk.type,
|
|
322
|
+
"metadata": chunk.response_metadata,
|
|
323
|
+
}
|
|
324
|
+
)
|
|
325
|
+
+ "\n\n"
|
|
326
|
+
)
|
|
327
|
+
# Update the interaction node with the fully generated text
|
|
328
|
+
actx = await AgentInterface.load_context_async()
|
|
329
|
+
try:
|
|
330
|
+
interaction_node.set_text_message(message=full_text)
|
|
331
|
+
interaction_node.add_tokens(total_tokens)
|
|
332
|
+
_Jac.spawn_call(
|
|
333
|
+
NodeAnchor.ref(interaction_node.id).architype,
|
|
334
|
+
AgentInterface.spawn_walker(
|
|
335
|
+
walker_name="update_interaction",
|
|
336
|
+
attributes={
|
|
337
|
+
"interaction_data": interaction_node.export(),
|
|
338
|
+
},
|
|
339
|
+
module_name="jivas.agent.action.update_interaction",
|
|
340
|
+
),
|
|
341
|
+
)
|
|
342
|
+
finally:
|
|
343
|
+
if actx:
|
|
344
|
+
actx.close()
|
|
345
|
+
|
|
346
|
+
except Exception as e:
|
|
347
|
+
AgentInterface.LOGGER.error(
|
|
348
|
+
f"Exception in streaming generator: {e}, {traceback.format_exc()}"
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
return StreamingResponse(
|
|
352
|
+
generate(response.generator),
|
|
353
|
+
media_type="text/event-stream",
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
else:
|
|
357
|
+
AgentInterface.LOGGER.error(
|
|
358
|
+
"Response is None or missing required attributes for streaming."
|
|
359
|
+
)
|
|
360
|
+
return {}
|
|
361
|
+
|
|
362
|
+
else:
|
|
363
|
+
response = response.response
|
|
364
|
+
ctx.close()
|
|
365
|
+
return response if response else {}
|
|
366
|
+
|
|
277
367
|
except Exception as e:
|
|
278
368
|
AgentInterface.EXPIRATION = None
|
|
279
369
|
AgentInterface.LOGGER.error(
|
|
280
370
|
f"an exception occurred: {e}, {traceback.format_exc()}"
|
|
281
371
|
)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return response if response else {}
|
|
372
|
+
ctx.close()
|
|
373
|
+
return {}
|
|
285
374
|
|
|
286
375
|
@staticmethod
|
|
287
376
|
def pulse(action_label: str, agent_id: str = "") -> dict:
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
jvserve/__init__.py,sha256=G5RMqYLR93brkiHRY7SgXqOtzchdd-v6TicDAX7ec6I,191
|
|
2
|
+
jvserve/cli.py,sha256=ltg-n-ZFsvitAGIhxY8xgwPI2CETLanZ_0bqrvsqqg8,4994
|
|
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=ccnMw5k1NtfK5ylNcvlCJE-Ene3tZigh6Q1gHRy7Sow,6026
|
|
7
|
+
jvserve/lib/jvlogger.py,sha256=RNiB9PHuBzTvNIQWhxoDgrDlNYA0PYm1SVpvzlqu8mE,4180
|
|
8
|
+
jvserve-2.0.10.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
9
|
+
jvserve-2.0.10.dist-info/METADATA,sha256=7Ptq6E2I9CPquslz_lrKi7rFAzqRIY2Qso6zmhbE1PM,4791
|
|
10
|
+
jvserve-2.0.10.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
|
11
|
+
jvserve-2.0.10.dist-info/entry_points.txt,sha256=HYyg1QXoLs0JRb004L300VeLOZyDLY27ynD1tnTnEN4,35
|
|
12
|
+
jvserve-2.0.10.dist-info/top_level.txt,sha256=afoCXZv-zXNBuhVIvfJGjafXKEiJl_ooy4BtgQwAG4Q,8
|
|
13
|
+
jvserve-2.0.10.dist-info/RECORD,,
|
jvserve-2.0.8.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
jvserve/__init__.py,sha256=tIOybimHYQXsh8xBeyN2-0sTRys82KAbagZSXK3HoK0,190
|
|
2
|
-
jvserve/cli.py,sha256=ltg-n-ZFsvitAGIhxY8xgwPI2CETLanZ_0bqrvsqqg8,4994
|
|
3
|
-
jvserve/lib/__init__.py,sha256=cnzfSHLoTWG9Ygut2nOpDys5aPlQz-m0BSkB-nd7OMs,31
|
|
4
|
-
jvserve/lib/agent_interface.py,sha256=i7KrsYTnYZR-wvh7cb2J77j0fBErHinu5300XCsd4UE,26496
|
|
5
|
-
jvserve/lib/agent_pulse.py,sha256=6hBF6KQYr6Z9Mi_yoWKGfdnW7gg84kK20Slu-bLR_m8,2067
|
|
6
|
-
jvserve/lib/file_interface.py,sha256=ccnMw5k1NtfK5ylNcvlCJE-Ene3tZigh6Q1gHRy7Sow,6026
|
|
7
|
-
jvserve/lib/jvlogger.py,sha256=RNiB9PHuBzTvNIQWhxoDgrDlNYA0PYm1SVpvzlqu8mE,4180
|
|
8
|
-
jvserve-2.0.8.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
9
|
-
jvserve-2.0.8.dist-info/METADATA,sha256=Wif2ZkPd7Vw5Q66pOr_iuVFduKjzaRDfQxxBCGrswlQ,4790
|
|
10
|
-
jvserve-2.0.8.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
11
|
-
jvserve-2.0.8.dist-info/entry_points.txt,sha256=HYyg1QXoLs0JRb004L300VeLOZyDLY27ynD1tnTnEN4,35
|
|
12
|
-
jvserve-2.0.8.dist-info/top_level.txt,sha256=afoCXZv-zXNBuhVIvfJGjafXKEiJl_ooy4BtgQwAG4Q,8
|
|
13
|
-
jvserve-2.0.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|