[Review Required]feat: support client context capabilities#3106
[Review Required]feat: support client context capabilities#3106BlairLeng wants to merge 2 commits into
Conversation
|
DeerFlow 团队好,再次感谢你们维护这个项目。 这个 PR 是关于 client context 讨论的一个小型后续实现。改动范围我尽量控制得比较小:主要是把经过安全裁剪的 我已经在本地完整跑过检查:
有时间的话,期待你们帮忙 review,也欢迎指出这个方向是否需要调整。 @WillemJiang @jimma Thank you very much |
This comment was marked as outdated.
This comment was marked as outdated.
941c8fe to
c544bc2
Compare
cca6acc to
7ed43f2
Compare
7ed43f2 to
09ce4ed
Compare
|
@BlairLeng, thanks for your contribution. Please update your GitHub profile->emails with the email of your git commit author to address the complaint of the CLA assistant. |
There was a problem hiding this comment.
Pull request overview
This PR introduces a lightweight context.client mechanism so custom frontends can pass client capabilities/preferences through the Gateway into runtime.context, and (optionally) into a compact hidden <client_context> reminder for agent/skill output shaping.
Changes:
- Add backend sanitization + prompt rendering helpers for
context.client, and forward sanitized client context intoruntime.contextfrom the Gateway. - Extend DynamicContextMiddleware to inject/update client context reminders alongside existing memory/date reminders.
- Add frontend typings, API docs, and regression tests covering sanitization, forwarding, and reminder injection behavior.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/core/threads/types.ts | Adds AgentClientContext typing and exposes it on AgentThreadContext. |
| backend/app/gateway/services.py | Sanitizes + forwards context.client into config["context"] (runtime-only). |
| backend/app/gateway/routers/thread_runs.py | Documents that context may include context.client. |
| backend/packages/harness/deerflow/runtime/client_context.py | New sanitization + prompt rendering utilities for client context. |
| backend/packages/harness/deerflow/agents/middlewares/dynamic_context_middleware.py | Injects rendered client context into hidden system reminders and supports same-day updates. |
| backend/docs/API.md | Documents request format and semantics for top-level context.client. |
| backend/tests/test_client_context.py | Adds unit tests for sanitization + rendering behavior. |
| backend/tests/test_gateway_services.py | Adds tests ensuring sanitized client context is runtime-only and respects explicit config precedence. |
| backend/tests/test_dynamic_context_middleware.py | Adds tests for reminder injection/update/clearing behavior for client context. |
| backend/tests/test_runtime_lifecycle_e2e.py | Improves cancellation test determinism by waiting until the fake agent is actually blocked. |
Comments suppressed due to low confidence (1)
backend/packages/harness/deerflow/runtime/client_context.py:97
- Same issue for
preferences:list(raw_preferences.items())[:_MAX_CLIENT_CONTEXT_ITEMS]builds a full list before slicing. Consider iterating and stopping after_MAX_CLIENT_CONTEXT_ITEMSto avoid unnecessary allocations on large client-provided payloads.
raw_preferences = raw_client.get("preferences")
if isinstance(raw_preferences, Mapping):
preferences: dict[str, str | int | float | bool] = {}
for raw_key, raw_value in list(raw_preferences.items())[:_MAX_CLIENT_CONTEXT_ITEMS]:
key = _clean_key(raw_key)
value = _clean_preference_value(raw_value)
if key is None or value is None:
continue
preferences[key] = value
| raw_capabilities = raw_client.get("capabilities") | ||
| if isinstance(raw_capabilities, Mapping): | ||
| capabilities: dict[str, bool] = {} | ||
| for raw_key, raw_value in list(raw_capabilities.items())[:_MAX_CLIENT_CONTEXT_ITEMS]: | ||
| key = _clean_key(raw_key) | ||
| if key is None or not isinstance(raw_value, bool): | ||
| continue | ||
| capabilities[key] = raw_value | ||
| if capabilities: |
| def _build_date_update_reminder(self, client_context: str | None = None) -> str: | ||
| current_date = datetime.now().strftime("%Y-%m-%d, %A") | ||
| return "\n".join( | ||
| [ | ||
| "<system-reminder>", | ||
| f"<current_date>{current_date}</current_date>", | ||
| "</system-reminder>", | ||
| ] | ||
| ) | ||
| lines = ["<system-reminder>", f"<current_date>{current_date}</current_date>"] | ||
| if client_context: | ||
| lines.extend(["", client_context]) | ||
| lines.append("</system-reminder>") | ||
| return "\n".join(lines) |
@WillemJiang Thanks for the reminder. I have added and verified both email addresses in my GitHub profile:
I also rewrote and rebased the PR branch earlier so the current commits are authored by:
Both current commits are linked to my GitHub account
I am not fully sure why CLA assistant left two comments in the PR timeline. My understanding is that the earlier failure comment was from the old commit author identity before I rewrote the branch, and the later comment reflects the current passing status. Please let me know if there is anything else I should adjust. |
|
@BlairLeng, please take some time to address Copilot's review comments. |
概要
这个 PR 增加了一个轻量的
context.client机制,使自定义前端可以把客户端能力和偏好传入 DeerFlow runtime。目标是让 agent 和 skill 能够根据当前请求来源的客户端做出更合适的输出决策,例如判断是否支持 artifact、CSV 下载、图表,或者是否只能返回纯文本结果。
改动
context.client的安全裁剪和 prompt 渲染 helpercontext.client转发到runtime.contextcontext.client的请求格式文档示例
{ "context": { "client": { "name": "custom-analytics-frontend", "capabilities": { "artifacts": true, "csv_download": true, "charts": true }, "preferences": { "csv": "present", "chart": "present" } } } }Closes #3105