feat(channels): support WeChat and WeCom image and file attachments - #95
Open
orhuoxu wants to merge 3 commits into
Open
feat(channels): support WeChat and WeCom image and file attachments#95orhuoxu wants to merge 3 commits into
orhuoxu wants to merge 3 commits into
Conversation
Collaborator
|
有一个需要合并前修复的问题: [P1] 微信/企微通过 微信: def download_media(self, context_token: str, media_id: str) -> bytes:
...
return response.content企微: response = client.get(...)
...
return response.content
if not data or len(data) > MAX_CHANNEL_MEDIA_BYTES:但这时整个响应已经通过
建议让这两个 |
Author
|
感谢你的细致审查和问题指正!确实是之前考虑得不够周全,我已经按照你的建议完成修改并补充了相关测试,再次感谢! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
StaffDeck 支持通过微信和企业微信接收入站图片、PDF 以及受支持的文本文件,并将附件接入既有对话链路。
用户可以直接在微信或企业微信会话中发送图片或文件。渠道适配器负责解析消息中的附件元数据、下载和解密媒体;统一附件桥接层负责将媒体暂存、解析为
ChatAttachment,并将其传递给既有的 AgentLoop、会话消息存储和模型输入流程。控制台的渠道会话详情支持图片预览和非图片附件下载。中文文件名通过 UTF-8 文件名参数传递,避免浏览器因响应头编码问题无法下载。
本实现复用 Web 端已有的附件暂存、解析、模型输入和消息元数据能力,不改变 AgentLoop、会话模型和渠道出站投递的核心语义。
支持范围
微信
image_item和file_item。kind=image。kind=file,保留文件名和文件大小。请识别并描述这张图片的内容。请读取并概述这个文件。full_url下载媒体。full_url时,使用官方downloadmedia接口。aiohttp,有限重试和流式读取;httpx回退;curl回退,使用独立 TLS 栈和 HTTP/1.1。curl回退兼容微信 CDN 的连接重置、传输超时以及异常Content-Length。微信 CDN 回退依赖部署环境提供系统
curl。如果系统没有curl,仅能使用前面的 Python HTTP 客户端。企业微信
image消息。file消息。mixed消息中的文本、图片。aeskey解密。media/get下载路径使用 access token 缓存、提前刷新和 token 失效重试。ChannelInboundAttachmentdataclass,保持持久化重放后的附件语义一致。统一入站附件协议
ChannelInbound增加attachments字段,携带当前入站消息的临时附件描述。每个
ChannelInboundAttachment包含:media_id:渠道侧媒体标识或媒体 URL。kind:image或file。filename:渠道提供的文件名或生成的回退文件名。content_type:渠道提供的 MIME 类型或适配器推断值。size:可选的媒体大小信息。download_params:渠道下载所需的临时参数,例如context_token、full_url、aes_key和预期大小。这些下载参数只用于处理当前入站消息,不作为长期对话附件元数据直接暴露给模型或前端。
微信媒体下载
微信图片和文件的
full_url指向微信 CDN,响应是经过加密的媒体内容。下载流程如下:微信媒体 URL 必须满足以下条件:
aiohttp路径使用流式读取和分块大小限制。httpx和系统curl回退路径会在接收响应后执行大小限制,因此部署环境仍应使用可信网络边界,并避免将不受信任的 URL 直接传入适配器。微信 CDN 可能在加密响应中包含尾随字节,或返回与实际传输内容不完全一致的
Content-Length。当前实现允许特定的 curl 传输结果继续进入 AES 解密,最终由解密、预期大小和图片 magic bytes 校验判断内容是否有效。企业微信媒体下载
企业微信 URL 下载流程如下:
企微智能机器人 URL 使用 WebSocket 所属事件循环下载;传统
media/get路径使用缓存的 access token。access token 失效时会强制刷新一次并重试,其他错误直接失败。附件桥接与解析
渠道附件由
inbound_attachments_to_chat统一桥接到 Web 附件管道:FFD9之后的渠道尾随字节。parse_chat_attachment解析附件。stage_chat_attachment将原始数据安全暂存到用户附件目录。sha256和 sandbox 路径的ChatAttachmentRead传递给对话请求。统一附件解析支持:
单个有效渠道附件上限为 25 MB。加密下载会预留 AES 分块所需的密文余量。
会话和模型链路
渠道附件进入既有
ChatTurnRequest.attachments字段,不新增独立的 AgentLoop 分支:附件元数据会随用户消息写入消息
metadata_json。Harness 会将附件物化到任务工作区,并在模型支持视觉输入时将有效图片作为视觉输入传递。如果渠道附件下载或解析失败,当前实现会记录异常并跳过该附件;入站事件本身不保证因此自动重试。此时 Agent 可能只收到默认的附件处理提示,而没有实际附件内容。
控制台
控制台行为:
filename和 UTF-8filename*,支持中文文件名。测试和验证
已覆盖的核心测试包括: