-
Notifications
You must be signed in to change notification settings - Fork 8.9k
fix: handle non-serializable objects in agent canvas SSE and state se… #14210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,20 @@ | |
| import logging | ||
| from functools import partial | ||
| from quart import request, Response, make_response | ||
|
|
||
|
|
||
| def _canvas_json_default(obj): | ||
| """Fallback serializer for canvas SSE events. | ||
|
|
||
| Agent components store functools.partial objects as deferred streaming | ||
| handles (see llm.py, agent_with_tools.py, message.py). These leak into | ||
| SSE event dicts via component input/output propagation and are not | ||
| JSON-serializable. This handler converts them to None so that downstream | ||
| consumers never receive opaque ``str(partial(...))`` representations. | ||
| """ | ||
| if callable(obj): | ||
| return None | ||
| raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable") | ||
|
Comment on lines
+24
to
+35
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log callable-to- This new fallback path currently drops data silently. Add a warning before coercion so production traceability is preserved when payload fields disappear. 🔧 Proposed fix def _canvas_json_default(obj):
@@
if callable(obj):
+ logging.warning(
+ "canvas_app: SSE JSON fallback coerced callable type=%s to None",
+ type(obj).__name__,
+ )
return None
raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")As per coding guidelines, 🤖 Prompt for AI Agents |
||
| from agent.component import LLM | ||
| from api.db import CanvasCategory | ||
| from api.db.services.canvas_service import CanvasTemplateService, UserCanvasService, API4ConversationService | ||
|
|
@@ -235,7 +249,7 @@ async def sse(): | |
| nonlocal canvas, user_id | ||
| try: | ||
| async for ans in canvas.run(query=query, files=files, user_id=user_id, inputs=inputs): | ||
| yield "data:" + json.dumps(ans, ensure_ascii=False) + "\n\n" | ||
| yield "data:" + json.dumps(ans, ensure_ascii=False, default=_canvas_json_default) + "\n\n" | ||
|
|
||
| commit_ok = CanvasReplicaService.commit_after_run( | ||
| canvas_id=req["id"], | ||
|
|
@@ -293,7 +307,7 @@ async def generate(): | |
| } | ||
| ) | ||
| ans.setdefault("data", {})["trace"] = trace_items | ||
| answer = "data:" + json.dumps(ans, ensure_ascii=False) + "\n\n" | ||
| answer = "data:" + json.dumps(ans, ensure_ascii=False, default=_canvas_json_default) + "\n\n" | ||
| yield answer | ||
|
|
||
| if event not in ["message", "message_end"]: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.