跳转至

状态和媒体

发布渠道运行时状态、解析媒体限制,并塑造原生负载。属于构建渠道插件指南的一部分。

运行时生命周期状态

对于渠道编写的运行时状态,ChannelAccountSnapshot.lifecycle 是 healthState 的继任者。现有插件在采用期间可以继续发布 healthState,并且核心派生的策略写入仍然受支持。没有移除日期;移除将等待外部渠道插件完成采用。

输入指示器

如果你的渠道在入站回复之外支持输入指示器,请在渠道插件上暴露 heartbeat.sendTyping(...)。核心会在心跳模型运行开始之前,使用已解析的心跳投递目标调用它,并复用共享的输入保活/清理生命周期。当平台需要显式停止信号时,添加 heartbeat.clearTyping(...)。

媒体源参数

使用 openclaw/plugin-sdk/account-helpers 中的 resolveChannelMediaMaxBytes(...) 解析账户媒体限制。通过 resolveChannelLimitMb 传入已合并账户的 mediaMaxMb;仅当账户/渠道限制缺失时,该辅助函数才应用代理默认值。其可选的字节结果必须到达实际的媒体加载器,并以任何传输上限为上限。当未配置限制时,保留加载器现有的默认值。

聚焦的账户辅助导入使设置和账户解析不依赖媒体分析运行时。旧的 media-runtime 导出仍可供现有外部插件使用,但新的和内置调用方应使用聚焦导入。

如果你的渠道添加了携带媒体源的消息工具参数,请通过 plugin.actions.describeMessageTool(...).mediaSourceParams 暴露这些参数名。核心使用该显式列表进行沙箱路径规范化和出站媒体访问策略,因此插件无需在核心共享层中为提供方专用的头像、附件或封面图参数提供特殊处理。

建议使用以操作为键的映射,例如 { "set-profile": ["avatarUrl", "avatarPath"] },这样无关操作就不会继承另一操作的媒体参数。对于有意在所有暴露操作之间共享的参数,扁平数组仍然有效。

必须为平台侧媒体抓取暴露临时公共 URL 的渠道,可以结合插件状态存储使用 openclaw/plugin-sdk/outbound-media 中的 createHostedOutboundMediaStore(...)。将平台路由解析和令牌强制逻辑保留在渠道插件中;共享辅助函数只负责媒体加载、过期元数据、分块行和清理。

prepareUrl({ mediaAccess }) 将主机授权的本地媒体访问转发给共享的出站加载器。为了兼容性,托管媒体容量默认采用 overflowPolicy: "evict-oldest"。当已发放的 URL 必须在过期前保持有效时,请使用 "reject-new",并为两个底层键值存储都配置 "reject-new",这样独立的写入方就无法逐出活动行。

当传输层必须拒绝某类负载时,使用 validateBeforePersist 检查受保护加载器的确切字节和元数据。将其缓冲区视为只读,并在创建能力或写入任何存储之前抛出异常以拒绝。在调用 read(...) 之前,使用 readMetadata(...) 对 bearer 请求进行身份验证,这样无效令牌和 HEAD 请求就不会加载已存储的媒体分块。

入站附件使用有序事实,而不是并行的 Media* 字段。使用 openclaw/plugin-sdk/channel-inbound 中的 toInboundMediaFacts(...) 规范化渠道记录,并在构建入站上下文时将它们作为 media 传入。当插件必须授权本地媒体读取时,从聚焦的 openclaw/plugin-sdk/media-local-roots 子路径导入 getAgentScopedMediaLocalRoots(...) 或 getAgentScopedMediaLocalRootsForSources(...)。代理作用域的根目录不会授予共享沙箱父目录访问权。要发送活动沙箱中生成的文件,请将其权威会话工作区作为第三个参数传给 getAgentScopedMediaLocalRoots(...),或作为 sessionWorkspaceDir 传给 sources 辅助函数。从可信的主机会话上下文中获取该值;切勿从请求的媒体路径推导。缺少该上下文时,仅工作区策略会故意拒绝沙箱路径。旧的 agent-media-payload 构建器/根门面是已弃用的兼容层。

原生负载整形

仅当负载发送方负责多附件分组时,才设置 outbound.sendPayloadGroupsMedia: true。当该发送方的持久负载和对账能力允许时,核心将为其保留一个多媒体列表。未显式选择启用时,普通附件保持逐项投递。

分组发送方必须在每次物理发送之前以及等待准备完成之后检查出站上下文的 signal,并在每个发送边界保留平台分发和当前所有者回调。仅声明通用负载支持并不会让插件承担这一责任。

如果你的渠道需要针对 message(action="send") 的提供方专属整形,请优先使用 actions.prepareSendPayload(...)。将原生卡片、块、嵌入内容或其他持久数据放在 payload.channelData.<channel> 下,让核心通过出站/消息适配器发送。仅将 actions.handleAction(...) 用作无法序列化和重试的负载的发送兼容回退。

对于发送操作,在调用 sendDurableMessageBatch(...) 时,保留可信上下文的 onPlatformSendDispatch、assertDirectAdapterHandoff 和 skipQueue。这些字段来自主机,而不是操作参数。在每次物理发送之前等待分发回调,然后在准备或限流等待之后、平台 I/O 之前立即调用同步断言。已关闭的所有者必须停止所有剩余的发送。

skipQueue: true 使与活动运行关联的发送不进入可重放的恢复流程。单独的 deliveryRetryOwner 字段控制由谁处理失败的投递;它不会扩展运行的权限。操作员发送保留正常的持久队列。不要序列化任一权限回调,也不要在面向模型的操作模式中暴露这些字段。

进度卡片交接

等待中的回复可以在其回复分发上下文中携带可选的主机拥有的 info.adoptProgressContinuation(receipt) 能力。可编辑进度适配器使用它来转移一张已可见的卡片,而不是用于发送替换卡片或将最终答案投递归因于该卡片。

排空并刷新现有草稿,重新检查 assertPlatformSendAuthorized,并传入其已确认的 messageId、已投递的 text、准备好的 snapshot 以及 channel/accountId/to/threadId 目标。暂存内容或模糊的发送不构成回执。只有 true 结果才会转移托管权:分离旧流,但不删除其消息。如果该能力缺失或拒绝,则保持普通回复投递,包括与等待文本并存的任何媒体或控件。

核心仅保留有界的展示数据及其回执。切勿序列化该能力、在操作参数中暴露它,或复用旧回合的回调。

投递后的置顶

outbound.pinDeliveredMessage 接收与消息发送相同的可选 assertDirectAdapterHandoff 回调。该字段将现有投递所有者的权限带入后续置顶操作;接受消息并不会授权在该所有者关闭后的后续置顶请求。在异步准备过程中保留该回调,并在每次提供商请求(包括重试)之前立即检查它。Telegram 会将其转发到现有的 assertPlatformSendAuthorized 传输选项,该选项会在账户限流释放每个请求后进行检查。

使用同步断言进行此检查。onPlatformSendDispatch 还会记录分发时间,并且不能替代权限断言。一旦置顶请求已提交,请保留其已接受的结果,而不是在响应后再次检查权限。可选置顶失败仍保持投递成功;必需置顶失败会在 sendDurableMessageBatch 的 partial_failed 结果中保留已发送的消息和回执。

新的置顶上下文字段是可选的,因此现有调用方和插件签名保持源码兼容。没有该字段的调用方保留其现有行为;请勿在配置、操作架构或存储负载中暴露它。有关置顶选项,请参阅消息展示与投递。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw