【免费下载链接】OpenAlice
Your one-person Wall Street. An AI trading agent covering equities, crypto, commodities, forex, and macro — from research through position entry, ongoing management, to exit.
本指南讲解 OpenAlice 的file-delivery技能(default/skills/file-delivery/SKILL.md):如何在 Connector 会话(Telegram、Discord、Slack、飞书)的最终回复中,用双括号引用把 Workspace 内的文件作为附件直接发送给人类用户,并阐明它何时应该使用 Inbox 通知(alice inbox push)而非普通回复。读完本文,你将掌握附件引用的完整语法与约束、Connector 服务端的解析与上传链路、附件的媒体类型推断规则,以及"回复附件"与"Inbox 报告"两种交付方式的准确取舍。
核心机制:在最终回复中用[[relative/path.ext]]引用文件
file-delivery技能的核心是一条极简约定:在 Connector 对话的最终回复中,把文件相对当前 Workspace 的路径用双括号包裹,Connector 服务即会在回复的对应位置把解析成功的文件作为附件上传。文件必须先创建或先验证存在,再在回复中引用。示例:
Here is the report. [[reports/summary.pdf]] The chart shows the comparison. [[reports/chart.png]]这条语法有四个必须遵守的要点:
- 引用必须写在代码区之外。把
[[...]]放进行内代码(backtick)或代码围栏(fenced code block)后,它会被解析器视为"讨论语法"而不触发上传——这正是"只想说明语法、不实际发文件"时的标准做法。 - 保持文本与附件的相对顺序。Connector 会在回复中引用所在的位置上传解析成功的文件,文本段落与附件的先后关系被原样保留(服务端实现见下文"文本与附件按位置分片")。
- 不产生 Inbox 条目。通过回复发送文件不会在 Inbox 中留下任何通知记录;Inbox 是独立于对话的另一个交付面。
- 路径指向"回复该会话"所属的 Workspace。若要发送**对等工作区(peer Workspace)**的文件,必须先把它复制进当前 Workspace 再引用,不允许跨界直接引用。
路径书写格式是严格的白名单式约束:直接用相对路径和扩展名即可,禁止使用file:前缀、绝对路径、..上级目录跳转、以及|label标签后缀。任何缺失、不可读或不支持的引用都会原样保留为字面文本,Connector 不会把未能解析的引用替换成占位符;因此"写了引用"本身不等于"文件已送达",交付结果需要以实际收到的附件为准。
交付限额(当前版本)
| 限额项 | 数值 | 说明 |
|---|---|---|
| 每次回复唯一文件数 | 最多5个 | 相同路径重复引用只上传一次(去重) |
| 单个文件大小 | 最多1 MiB | 超过则引用无法解析为附件 |
| 字节完整性 | 文件字节原样保留 | 不重编码、不缩放(但编码归一化的报告例外,见下) |
服务端的硬性约束与这两条完全一致:MAX_CONNECTOR_ATTACHMENT_BYTES = 1024 * 1024、MAX_CONNECTOR_ATTACHMENTS = 5定义在 packages/connector-protocol/src/types.ts,且connectorAttachmentSchema用sizeBytes: z.number().int().min(0).max(MAX_CONNECTOR_ATTACHMENT_BYTES)在协议层就拒绝超限附件。连接器在回复里实际解析时也按"最多 5 个"截断:resolved.size >= 5即停止解析后续引用(services/connector/src/core/delivery-manager.ts)。
各平台的呈现方式
- Telegram:PNG / JPEG / WebP 以**图片(photo)形式发送,其余受支持的文件类型以文档(document)**形式发送。
- GUI 聊天界面(OpenAlice 的 web 会话界面):渲染预览,并在右侧面板打开文档;点击图片时弹出预览对话框。
- 终端(Terminal):只显示文本、不执行上传——终端会话没有附件通道,引用只会以字面文本展示。
注意:Telegram 发送图片还是文档,取决于 reply-directives.ts 中的媒体类型推断,而非 Telegram 侧的魔数判断(见下文"媒体类型推断")。
贴纸(Sticker)交付
sticker/*.png与sticker/*.webp路径走贴纸交付通道(在支持贴纸的平台上按贴纸发送,而非普通图片)。可用的贴纸包及其用法以**已安装的贴纸技能(sticker Skill)**为准——OpenAlice 仓库内置了alice-color与alice-ink两套贴纸包(default/stickers),每套含 20 张 PNG 与一张 JSON 清单;引用的路径要与已安装贴纸包中的实际文件名匹配。
解析与交付的源码级链路
回复附件的完整链路在Connector Service的DeliveryManager.deliverOwnerChat中实现(services/connector/src/core/delivery-manager.ts),核心步骤:
- 解析引用:
parseReplyDirectives(message.text)扫出文本中所有合法的[[path]]引用(来自 packages/connector-protocol/src/content-references.ts 的parseContentReferences,Connector 侧重导出为parseReplyDirectives)。 - 解析文件:对每个去重后的路径,优先尝试
readWorkspaceFile(workspaceId, path)从回复会话所属的 Workspace读取;若路径命中市场图表引用(market/...),则走renderMarket渲染(见 reply-directives.ts 对parseMarketReference的优先判断)。任何解析失败(如文件不存在、不可读)都被静默吞掉,引用保持字面文本。 - 文本与附件按位置分片:把回复按引用位置切分为
{text}与{path, attachment}交替的片段序列,先发送首段文本(transport 的"实时回复"),再按顺序依次sendOwnerText/sendOwnerFile——这就是"回复中文本与附件顺序被保留"的实现来源(delivery-manager.ts)。 - 媒体类型推断:
replyMedia(path)决定附件以file/image/sticker哪种呈现方式上传,规则见下文。 - 字节与哈希校验:附件携带
contentSha256与sizeBytes;reply-media.spec.ts明确测试了"损坏媒体(哈希不符)在上传前被拒绝"(services/connector/src/adapters/reply-media.spec.ts),避免把坏字节发给用户。
媒体类型推断规则
来自 services/connector/src/core/reply-directives.ts,判断顺序是:
| 优先级 | 条件 | 呈现类型 |
|---|---|---|
| 1 | 命中市场引用(parseMarketReference(path),如market/okx|BTC/USDT:USDT/4h) | image(渲染图表) |
| 2 | sticker/目录下且扩展名为.png/.webp(大小写不敏感) | sticker |
| 3 | 扩展名为.png/.jpg/.jpeg/.webp(大小写不敏感) | image |
| 4 | 其余一切路径 | file |
这套规则与测试完全一致:report/chart.PNG→ image、report/weekly.pdf→ file、sticker/notes.txt→ file(因为不满足贴纸扩展名条件)(services/connector/src/core/reply-directives.spec.ts)。
平台适配:sendOwnerFile 的实现差异
各 Connector 适配器都实现了sendOwnerFile(attachment, presentation),但对presentation的利用程度不同:
- Telegram最完整地利用
ReplyMedia:image按 photo、sticker按贴纸发送; - Discord / Slack在 discord.ts 与 slack.ts 中把
_presentation参数忽略(_前缀表明未使用),一律按普通文件上传——它们的消息体系本身就把图片作为附件展示; - 飞书在 feishu.ts 中接收
presentation参数参与上传分发。
三个平台的通用约束(reply-media.spec.ts):只向已关联的 owner发送(未关联 owner 时先抛错、不产生上传);上传失败会记录delivery.failed并把适配器健康状态降级为degraded,同时向用户回发Could not send file: <path>. Upload failed; please try again.(delivery-manager.ts)。
解析器的语法豁免(escape 与代码区)
parseContentReferences的正则扫描(content-references.ts)会对以下形式整体跳过:代码围栏(``` 与~~~)、行内代码(`...`)、反斜杠转义(\[[...]])。content-references.spec.ts用一整段样例验证了这些豁免:
`[[inline.md]]` ```md [[fenced.md]][[escaped.md]] [[NVDA]] [[../private.md]] [[/absolute.pdf]] [[https://example.com/a.pdf]] [[./README]]
其中 `[[../private.md]]`、`[[/absolute.pdf]]`、`[[https://example.com/a.pdf]]` 都不会被当作文件引用(`isFileReference` 拒绝以 `/` 开头、含 `..` 段、以协议前缀开头的路径,见 [content-references.ts](https://link.gitcode.com/i/23a14d45cc4719806f0f034af035fa25))——这正是 SKILL.md 中"禁止绝对路径、`..`"约束的底层实现。行内代码与围栏内的引用则被解析器跳过、永远保持字面文本。 ## 什么时候该用 Inbox:回复附件 vs 通知报告 **Inbox 是 OpenAlice 面向人类的外部通知与报告面**:警报、发现、报告、或需要人类关注并**应有独立交付记录**的内容,才使用 Inbox。而"当前对话中用户索要的文件"直接在回复里发送即可——**它不会仅仅因为是一个文件就需要一条 Inbox 记录**。 三条职责边界(与 [default/skills/alice/references/collaboration.md](https://link.gitcode.com/i/e30269a1d35e219c2a9e9e932504e998) 的"命令模型"表一致): | 交付面 | 职责 | 不负责 | |---|---|---| | 回复(`[[...]]`) | 当前会话内给人类的即时回复附件 | 独立通知、报告记录 | | Inbox(`alice inbox push`) | 面向人类的通知、报告、后续跟进 | 通用对等聊天、文件存储 | | 对等会话(`alice conversation`) | Agent 到 Agent 的手递手 | 人类通知 | **避免重复投递**:除非确实需要一条独立的通知或报告交接,不要把回复内容再复制进 Inbox。文件与 Git 承载工作产物,Inbox 负责把结果告知人类,对等会话负责 Agent 间交接——三者各司其职。 ### 用 Inbox 推送带附件的报告 需要给人类发一条**独立通知**(例如无人值守任务的结果、需要专门关注度的报告)时,用 `alice inbox push`: ```bash # 方式一:body 内联引用——Markdown 正文 + 活文件引用 alice inbox push --body 'See [[report/summary.pdf]]' # 方式二:--body-file 把 Markdown 文件本身发布为通知正文 alice inbox push --body-file report/summary.md两处的语义细节(来自 default/skills/alice/references/collaboration.md 与 src/tool/inbox-push.ts 的实现):
--body-file发布的是该 Markdown 文件本身,而--body中内联的[[relative/path.ext]]引用是活引用:它们相对发布方 Workspace 根目录解析,且保持"活着"——读者之后仍能跟随引用打开对应文件。- 发布时正文被冻结(frozen):正文文本在发布那一刻定稿,但文件引用保持动态解析;每个被引用的文件会计算
sha256:前缀的发布哈希作为该文件版本的标识,写入fileRevisions(inbox-push.ts)。若希望 Git 保存发布内容,请先提交文件再发布。 - 代码示例中的引用与缺失路径在 Inbox 正文中同样保持字面文本。
- 每条附件在
alice inbox read的files[]中返回:可直接使用的absolutePath、原始relativePath、以及可用时的发布revision;若absolutePath为 null(Workspace 不可用或路径不安全),不要猜测补全,可用alice peer path --id <workspaceId>解析对等 Workspace 根目录后用 Agent 原生的 Read/Search/Glob/Git 能力检查。
查看近期投递:
alice inbox read --limit 5 # 最近 5 条 alice inbox read --self # 只看本 Workspace 自己的推送inbox push/inbox read/inbox ask在aliceCLI 中是顶层inbox组的动词(src/server/cli-commands.ts);inbox_push同时以 Workspace 工具(tool)的形式暴露给 Agent,其工具描述明确写着:"body 是 Markdown,用[[report/file.pdf]]指向相对此 Workspace 根的活文件;CLI--body-file把 Markdown 文件读作发布正文;普通回复用于会话内响应;Inbox 不是文件存储,也不是 Agent 间通道;来源(origin)自动记录。"(src/tool/inbox-push.ts)——工具会自动为推送条目盖上来源(run / session)戳,供alice provenance show --kind inbox追溯。
常用协作命令速查(与 file-delivery 直接相关)
alice --help # 发现研究/协作命令组 alice inbox push --body 'Finished — see [[research/report.md]] for evidence.' alice inbox push --body-file research/report.md alice inbox read --limit 5 alice inbox read --self alice inbox ask --id <entryId> --prompt 'Why did you send this result?' --await alice conversation create --ws-id <workspaceId> --prompt '...' # Agent 间会话(非 Inbox) alice peer path --id <workspaceId> # 解析对等 Workspace 根目录注意:Inbox 只通知人类;Agent 到 Agent 的完成通知没有"主动推送总线",普通对等交流必须走alice conversation,配合--await/await/read/collect拉取回复。
常见误区与排错清单
结合 SKILL.md 的约束与解析器实现,最容易踩的坑如下:
- 引用写在代码区里→ 被解析器豁免,永远不触发上传。想发送文件,引用必须位于正文;想讨论语法,引用放进行内代码或代码围栏。
- 路径写错格式:
file:前缀、绝对路径(/开头)、..段、|label后缀都会被isFileReference拒绝 → 引用保持字面文本,不会交付。 - 文件不在回复会话的 Workspace:peer Workspace 的文件必须先复制进当前 Workspace再引用。
- 超限:超过 5 个唯一文件、或单个文件超过 1 MiB → 超出的引用无法解析(协议层
connectorAttachmentSchema直接拒绝超限附件)。 - 写了引用 ≠ 已送达:缺失/不可读/不支持的引用保持字面文本,Connector 不会提示你失败(仅在上传阶段失败时才回发
Could not send file提示)。交付后应通过收到的附件确认,而不是看回复文本。 - 混淆交付面:会话内索要的文件直接用回复发送,不要机械地再复制一条 Inbox;需要独立通知/报告记录时才用
alice inbox push,避免重复投递。 - 贴纸路径:只有
sticker/*.png、sticker/*.webp且与已安装贴纸包实际文件名匹配时才走贴纸通道(reply-directives.ts);用错扩展名或路径会退化为file或保持字面。
延伸阅读
- 技能原文:default/skills/file-delivery/SKILL.md
alice协作命令全貌(peer / conversation / inbox / issue / provenance 等):default/skills/alice/references/collaboration.md- 共享引用解析器与文件引用白名单:packages/connector-protocol/src/content-references.ts
- Connector 回复解析与附件限额:packages/connector-protocol/src/types.ts
- 回复分片、上传与媒体推断:services/connector/src/core/delivery-manager.ts、services/connector/src/core/reply-directives.ts
- 多平台附件上传行为测试:services/connector/src/adapters/reply-media.spec.ts
- Inbox 推送工具实现:src/tool/inbox-push.ts
- Inbox 数据与文件语义:docs/inbox-content.md、docs/connector-service.md
【免费下载链接】OpenAlice
Your one-person Wall Street. An AI trading agent covering equities, crypto, commodities, forex, and macro — from research through position entry, ongoing management, to exit.
相关推荐
GitHub Copilot SDK 图像输入(Image Input)完整指南:通过 file / blob 附件向 Copilot 会话发送图片
GitHub Copilot SDK 图像输入(Image Input)完整指南:通过 file / blob 附件向 Copilot 会话发送图片 导读 本文
人工智能AI AgentAgent 框架工具调用ClawX 基于 OpenClaw message 工具交付记录的生成文件附件恢复机制(recover-message-tool-file-attachments 实现解析)
ClawX 基于 OpenClaw message 工具交付记录的生成文件附件恢复机制(recover message tool file attachment
人工智能AI 应用桌面应用交互助手DeepSeek Harness 对话式 Schedule 交付:用普通会话轮次替代持久回执的设计取舍
DeepSeek Harness 对话式 Schedule 交付:用普通会话轮次替代持久回执的设计取舍 导读 :DeepSeek Harness(Everyth
人工智能AI AgentAgent 框架DeepSeek
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考