jvserve 2.0.13__py3-none-any.whl → 2.0.15__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.13"
7
+ __version__ = "2.0.15"
8
8
  __supported__jivas__versions__ = ["2.0.0"]
@@ -159,77 +159,211 @@ class AgentInterface:
159
159
 
160
160
  return response
161
161
 
162
+ @staticmethod
163
+ def get_action_data(agent_id: str, action_label: str) -> dict:
164
+ """Retrieves the data for a specific action of an agent."""
165
+
166
+ action_data = {}
167
+ ctx = AgentInterface.load_context()
168
+
169
+ if not ctx:
170
+ return {}
171
+
172
+ # TODO : raise error in the event agent id is invalid
173
+ AgentInterface.LOGGER.debug(
174
+ f"attempting to interact with agent {agent_id} with user root {ctx.root}..."
175
+ )
176
+
177
+ try:
178
+ actions = _Jac.spawn_call(
179
+ ctx.entry_node.architype,
180
+ AgentInterface.spawn_walker(
181
+ walker_name="list_actions",
182
+ attributes={"agent_id": agent_id},
183
+ module_name="agent.action.list_actions",
184
+ ),
185
+ ).actions
186
+
187
+ if actions:
188
+ for action in actions:
189
+ if action.get("label") == action_label:
190
+ action_data = action
191
+ break
192
+
193
+ except Exception as e:
194
+ AgentInterface.EXPIRATION = None
195
+ AgentInterface.LOGGER.error(
196
+ f"an exception occurred: {e}, {traceback.format_exc()}"
197
+ )
198
+
199
+ ctx.close()
200
+ return action_data
201
+
162
202
  @staticmethod
163
203
  async def action_walker_exec(
164
- agent_id: str = Form(...), # noqa: B008
165
- module_root: str = Form(...), # noqa: B008
166
- walker: str = Form(...), # noqa: B008
204
+ agent_id: Optional[str] = Form(None), # noqa: B008
205
+ action: Optional[str] = Form(None), # noqa: B008
206
+ walker: Optional[str] = Form(None), # noqa: B008
167
207
  args: Optional[str] = Form(None), # noqa: B008
168
208
  attachments: List[UploadFile] = File(default_factory=list), # noqa: B008
169
209
  ) -> JSONResponse:
170
- """Execute a named walker exposed by an action within context; capable of handling JSON or file data depending on request"""
210
+ """
211
+ Execute a named walker exposed by an action within context.
212
+ Capable of handling JSON or file data depending on request.
213
+
214
+ Args:
215
+ agent_id: ID of the agent
216
+ action: Name of the action
217
+ walker: Name of the walker to execute
218
+ args: JSON string of additional arguments
219
+ attachments: List of uploaded files
220
+
221
+ Returns:
222
+ JSONResponse: Response containing walker output or error message
223
+ """
224
+ ctx = None
225
+ try:
226
+ # Validate required parameters
227
+ if walker is None or agent_id is None or action is None:
228
+ AgentInterface.LOGGER.error("Missing required parameters")
229
+ return JSONResponse(
230
+ status_code=400, # 400 (Bad Request)
231
+ content={"error": "Missing required parameters"},
232
+ )
171
233
 
172
- response = JSONResponse(status_code=500, content="unable to complete request")
234
+ # Get action data to resolve module
235
+ if agent_id is None or action is None:
236
+ AgentInterface.LOGGER.error("agent_id and action must not be None")
237
+ return JSONResponse(
238
+ status_code=400,
239
+ content={"error": "agent_id and action must not be None"},
240
+ )
173
241
 
174
- try:
242
+ action_data = AgentInterface.get_action_data(agent_id, action)
243
+ if not action_data:
244
+ AgentInterface.LOGGER.error(
245
+ f"Action {action} not found for agent {agent_id}"
246
+ )
247
+ return JSONResponse(
248
+ status_code=404,
249
+ content={"error": "Action not found"},
250
+ )
251
+
252
+ module_root = (
253
+ action_data.get("_package", {}).get("config", {}).get("module_root", "")
254
+ )
255
+ if not module_root:
256
+ AgentInterface.LOGGER.error(
257
+ f"Module not found for action {action} of agent {agent_id}"
258
+ )
259
+ return JSONResponse(
260
+ status_code=404,
261
+ content={"error": "Module not found"},
262
+ )
263
+
264
+ # Load execution context
265
+ ctx = await AgentInterface.load_context_async()
266
+ if not ctx:
267
+ AgentInterface.LOGGER.error(f"Unable to execute {walker}")
268
+ return JSONResponse(
269
+ status_code=500,
270
+ content={"error": "Failed to load execution context"},
271
+ )
175
272
 
176
- # add agent id as a standard
273
+ # Prepare attributes
177
274
  attributes: Dict[str, Any] = {"agent_id": agent_id}
178
275
 
179
- # add any other args
276
+ # Parse additional arguments if provided
180
277
  if args:
181
- attributes.update(json.loads(args))
278
+ try:
279
+ attributes.update(json.loads(args))
280
+ except json.JSONDecodeError as e:
281
+ AgentInterface.LOGGER.error(f"Invalid JSON in args: {e}")
282
+ return JSONResponse(
283
+ status_code=400,
284
+ content={"error": "Invalid JSON in arguments"},
285
+ )
182
286
 
183
- # Processing files if any were uploaded
287
+ # Process uploaded files
184
288
  if attachments:
185
289
  attributes["files"] = []
186
290
  for file in attachments:
187
- attributes["files"].append(
188
- {
189
- "name": file.filename,
190
- "type": file.content_type,
191
- "content": await file.read(),
192
- }
193
- )
291
+ try:
292
+ attributes["files"].append(
293
+ {
294
+ "name": file.filename,
295
+ "type": file.content_type,
296
+ "content": await file.read(),
297
+ }
298
+ )
299
+ except Exception as e:
300
+ AgentInterface.LOGGER.error(
301
+ f"Failed to process file {file.filename}: {e}"
302
+ )
303
+ continue # Skip problematic files or return error if critical
194
304
 
195
- if not agent_id or not walker or not module_root:
196
- AgentInterface.LOGGER.error("missing parameters")
197
- return JSONResponse(
198
- status_code=401, content="missing required parameters"
199
- )
305
+ # Execute the walker
306
+ walker_response = _Jac.spawn_call(
307
+ ctx.entry_node.architype,
308
+ AgentInterface.spawn_walker(
309
+ walker_name=walker,
310
+ attributes=attributes,
311
+ module_name=f"{module_root}.{walker}",
312
+ ),
313
+ ).response
200
314
 
201
- except Exception as e:
202
- AgentInterface.LOGGER.error(
203
- f"an exception occurred: {e}, {traceback.format_exc()}"
204
- )
205
- return JSONResponse(status_code=500, content="internal server error")
315
+ # Handle different response types appropriately
316
+ try:
317
+ # If it's already a proper Response object, return as-is
318
+ if isinstance(walker_response, requests.Response):
319
+ return walker_response
206
320
 
207
- ctx = await AgentInterface.load_context_async()
208
- if ctx:
209
- # compose full module_path
210
- module = f"{module_root}.{walker}"
321
+ # If it's a Pydantic model or similar complex object with dict representation
322
+ if hasattr(walker_response, "dict"):
323
+ return JSONResponse(status_code=200, content=walker_response.dict())
211
324
 
212
- try:
213
- response = _Jac.spawn_call(
214
- ctx.entry_node.architype,
215
- AgentInterface.spawn_walker(
216
- walker_name=walker,
217
- attributes=attributes,
218
- module_name=module,
219
- ),
220
- ).response
325
+ # If it's a list of complex objects
326
+ if (
327
+ isinstance(walker_response, list)
328
+ and len(walker_response) > 0
329
+ and hasattr(walker_response[0], "dict")
330
+ ):
331
+ return JSONResponse(
332
+ status_code=200,
333
+ content=[item.dict() for item in walker_response],
334
+ )
335
+
336
+ # For other JSON-serializable types
337
+ try:
338
+ return JSONResponse(status_code=200, content=walker_response)
339
+ except TypeError:
340
+ # Fallback to string representation if not directly JSON-serializable
341
+ return JSONResponse(
342
+ status_code=200, content={"result": str(walker_response)}
343
+ )
221
344
 
222
345
  except Exception as e:
223
- AgentInterface.EXPIRATION = None
224
- AgentInterface.LOGGER.error(
225
- f"an exception occurred: {e}, {traceback.format_exc()}"
346
+ AgentInterface.LOGGER.error(f"Failed to format walker response: {e}")
347
+ return JSONResponse(
348
+ status_code=500,
349
+ content={"error": "Failed to format response", "details": str(e)},
226
350
  )
227
- else:
228
- AgentInterface.LOGGER.error(f"unable to execute {walker}")
229
351
 
230
- ctx.close()
231
-
232
- return response
352
+ except Exception as e:
353
+ AgentInterface.EXPIRATION = None
354
+ AgentInterface.LOGGER.error(
355
+ f"Exception occurred: {str(e)}\n{traceback.format_exc()}"
356
+ )
357
+ return JSONResponse(
358
+ status_code=500,
359
+ content={"error": "Internal server error", "details": str(e)},
360
+ )
361
+ finally:
362
+ if ctx:
363
+ try:
364
+ ctx.close()
365
+ except Exception as e:
366
+ AgentInterface.LOGGER.error(f"Error closing context: {str(e)}")
233
367
 
234
368
  class InteractPayload(BaseModel):
235
369
  """Payload for interacting with the agent."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jvserve
3
- Version: 2.0.13
3
+ Version: 2.0.15
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=S9zx3emgI3a17M2NmUFp3sdzrZ9SDFwDKYAUR_TjDxE,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=d2trRXgLjUzciGSRwYD2Rl-TPnyJVpUKrgG1iU7CGyw,37768
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.15.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
9
+ jvserve-2.0.15.dist-info/METADATA,sha256=eXjQb1zag7Si-czz5V4wX60-6wr9E2eyz3yIETUF9i0,4791
10
+ jvserve-2.0.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
+ jvserve-2.0.15.dist-info/entry_points.txt,sha256=HYyg1QXoLs0JRb004L300VeLOZyDLY27ynD1tnTnEN4,35
12
+ jvserve-2.0.15.dist-info/top_level.txt,sha256=afoCXZv-zXNBuhVIvfJGjafXKEiJl_ooy4BtgQwAG4Q,8
13
+ jvserve-2.0.15.dist-info/RECORD,,
@@ -1,13 +0,0 @@
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,,