Skill全文级超长内容转文件:新增host发文件能力(issue #163) #169

Merged
Yushu merged 1 commit from feat/163-file-egress-capability into main 2026-08-20 03:04:27 +00:00
Member

Closes #163

What

从 issue #154 拆出的第三级"文件"部分:设计并落地 host 侧发文件能力,inject_skills 全文级超长内容改为转文件,不再只是截断+提示。

  • 新增 CapabilitySet.file + EgressPort.send_file(chat_id, content: str, *, filename: str) -> str,形状仿 sticker/voice(能力位+方法成对,位为假时 core 不走这条路径)——落点经 design-verify 核对 ArisePorts docstring 判据(resource/economic_hook/is_group_admin 三个可选 port 都是"host 要不要接一层带载荷的服务",而发文件是一次纯粹的发送动作,精确落在"能力位+方法成对"这一类,不新开 ArisePorts 可选字段)
  • inject_skills_handle_inject_skills)全文级内容超过 arise_skill_full_text_max_chars 时,capabilities.file 为真且本轮发送预算未耗尽才改经 send_file 发送,否则维持 issue #154 落地的截断+提示既有降级路径
  • 关键接线:待发文件真正流经既有的 _PendingSend/_flush/_send_pending 管线,不是对 egress.send_file 的孤立裸调用——因此自动获得 MAX_SENDS_PER_TURN 预算约束(与 send_message/edit 降级路径共享同一个 turn 级预算)、Sent Log 句柄记录(可 self_recall)、issue #95 的失败回灌保护,避免绕开发送预算无限发文件,也避免制造 ADR-0013 点名的"孤儿消息"
  • _PendingSend 新增 filename/file_payload 字段,与既有 content 字段分开:content 只放一句人类可读的短摘要(记进 Sent Log/Delta),真正发给平台的原文只在 file_payload 里——避免技能全文经 _append_delta 原样写回下一轮上下文,把"转文件省 token"这件事自己抵消
  • 预算耗尽时不报错,退回截断+提示(inject_skills 是信息检索工具,有兜底内容可给,不照搬 edit 降级路径的硬错误)

Design-Verify

两轮独立方案 + 对抗式交叉核实 + 合并,产出比两份原方案都更完整的最终决策:两份原方案都遗漏了"必须流经 _PendingSend/_flush 管线"这一关键要求(会绕开 MAX_SENDS_PER_TURN 且制造孤儿消息),也都没意识到"技能全文经 Delta 回灌抵消转文件收益"这个问题——这两点是合并阶段新发现并采纳进最终方案的。

Review 修复

两轴 review + 对抗式 Verify 确认 5 处文档漂移问题(无功能性 bug)并已修复:

  • ADR-0004 新增更新节的悬空引用(指向 ADR-0006 但后者未同步)—— 已给 ADR-0006 补一节纠正"没有发文件能力"的过时断言
  • docs/design.md 的"技能"条未跟随 CONTEXT.md 同步更新——已同步
  • ADR-0012 新增节标题"两个入口共同消费"漏计既有的第三个消费方(edit 降级路径)——已订正为"新增第三个消费方"
  • tests/test_skill.pyTestRenderSkillFull docstring 仍写"issue #163 落地前的过渡行为"——已同步 skill.py 的新措辞

Test plan

  • uv run pytest -q:1999 passed
  • uv run ruff check src/ tests/:全通过
  • uv run lint-imports:2 kept, 0 broken
  • ty check:47 diagnostics(与 main 基线一致,无新增)
  • mutation testing:_handle_inject_skills 的能力位/预算耗尽守卫 + _send_pending 的 file 分支路由/参数传递逐一变异验证测试能捕获
Closes #163 ## What 从 issue #154 拆出的第三级"文件"部分:设计并落地 host 侧发文件能力,`inject_skills` 全文级超长内容改为转文件,不再只是截断+提示。 - 新增 `CapabilitySet.file` + `EgressPort.send_file(chat_id, content: str, *, filename: str) -> str`,形状仿 `sticker`/`voice`(能力位+方法成对,位为假时 core 不走这条路径)——落点经 design-verify 核对 `ArisePorts` docstring 判据(`resource`/`economic_hook`/`is_group_admin` 三个可选 port 都是"host 要不要接一层带载荷的服务",而发文件是一次纯粹的发送动作,精确落在"能力位+方法成对"这一类,不新开 `ArisePorts` 可选字段) - `inject_skills`(`_handle_inject_skills`)全文级内容超过 `arise_skill_full_text_max_chars` 时,`capabilities.file` 为真且本轮发送预算未耗尽才改经 `send_file` 发送,否则维持 issue #154 落地的截断+提示既有降级路径 - **关键接线**:待发文件真正流经既有的 `_PendingSend`/`_flush`/`_send_pending` 管线,不是对 `egress.send_file` 的孤立裸调用——因此自动获得 `MAX_SENDS_PER_TURN` 预算约束(与 `send_message`/`edit` 降级路径共享同一个 turn 级预算)、Sent Log 句柄记录(可 `self_recall`)、issue #95 的失败回灌保护,避免绕开发送预算无限发文件,也避免制造 ADR-0013 点名的"孤儿消息" - `_PendingSend` 新增 `filename`/`file_payload` 字段,与既有 `content` 字段分开:`content` 只放一句人类可读的短摘要(记进 Sent Log/Delta),真正发给平台的原文只在 `file_payload` 里——避免技能全文经 `_append_delta` 原样写回下一轮上下文,把"转文件省 token"这件事自己抵消 - 预算耗尽时不报错,退回截断+提示(`inject_skills` 是信息检索工具,有兜底内容可给,不照搬 `edit` 降级路径的硬错误) ## Design-Verify 两轮独立方案 + 对抗式交叉核实 + 合并,产出比两份原方案都更完整的最终决策:两份原方案都遗漏了"必须流经 `_PendingSend`/`_flush` 管线"这一关键要求(会绕开 `MAX_SENDS_PER_TURN` 且制造孤儿消息),也都没意识到"技能全文经 Delta 回灌抵消转文件收益"这个问题——这两点是合并阶段新发现并采纳进最终方案的。 ## Review 修复 两轴 review + 对抗式 Verify 确认 5 处文档漂移问题(无功能性 bug)并已修复: - ADR-0004 新增更新节的悬空引用(指向 ADR-0006 但后者未同步)—— 已给 ADR-0006 补一节纠正"没有发文件能力"的过时断言 - `docs/design.md` 的"技能"条未跟随 CONTEXT.md 同步更新——已同步 - ADR-0012 新增节标题"两个入口共同消费"漏计既有的第三个消费方(`edit` 降级路径)——已订正为"新增第三个消费方" - `tests/test_skill.py` 的 `TestRenderSkillFull` docstring 仍写"issue #163 落地前的过渡行为"——已同步 `skill.py` 的新措辞 ## Test plan - [x] `uv run pytest -q`:1999 passed - [x] `uv run ruff check src/ tests/`:全通过 - [x] `uv run lint-imports`:2 kept, 0 broken - [x] `ty check`:47 diagnostics(与 main 基线一致,无新增) - [x] mutation testing:`_handle_inject_skills` 的能力位/预算耗尽守卫 + `_send_pending` 的 file 分支路由/参数传递逐一变异验证测试能捕获
新增 CapabilitySet.file + EgressPort.send_file,形状仿 sticker/voice(能力
位+方法成对、位为假时 core 不走这条路径)。inject_skills 全文级内容超过
arise_skill_full_text_max_chars 时,host 声明了该能力才改经 send_file 发
送,未声明时维持既有截断+提示。文件发送真正流经既有 _PendingSend/_flush/
_send_pending 管线,复用 MAX_SENDS_PER_TURN 预算与 Sent Log 句柄机制,避
免绕开发送预算或制造孤儿消息;_PendingSend 拆出 filename/file_payload 与
content 分开,防止技能全文经 Delta 回灌抵消"转文件省 token"的收益。
Yushu merged commit 0d17f538d0 into main 2026-08-20 03:04:27 +00:00
Yushu deleted branch feat/163-file-egress-capability 2026-08-20 03:04:27 +00:00
Sign in to join this conversation.
No description provided.