Skip to content

feat: 支持结构化图片消息输入 - #3

Open
qiuYliangM wants to merge 1 commit into
Pinvou:pinvou3-cleanfrom
qiuYliangM:feat/structured-image-input
Open

feat: 支持结构化图片消息输入#3
qiuYliangM wants to merge 1 commit into
Pinvou:pinvou3-cleanfrom
qiuYliangM:feat/structured-image-input

Conversation

@qiuYliangM

Copy link
Copy Markdown

概述

为底座增加结构化图片消息输入能力:用户消息可携带 workspace 本地图片引用,请求前临时物化为 Base64 图片块,持久化、日志、compaction 全程不含 Base64。

背景

pinvou3 普通会话原生图片输入改造的底座部分。原 Op::SendMessage 只接受 String,宿主无法提交图片块;Anthropic 客户端会把 data URL 当远程 URL 发送;image_analyze 缺独立大小限制、仅凭扩展名判型、硬编码 temperature 导致 kimi-for-coding 等模型 400 拒绝。

变更

  • Op::SendMessage 新增 input: Option<UserMessageInput>(UserInputBlock::{Text, LocalImage}),纯文本调用传 None,行为零变化
  • 新增 vision/image_input.rs:workspace 相对路径校验(拒绝对路径/../symlink 逃逸)、20MB 统一上限、PNG/JPEG/GIF/WebP/BMP 魔数嗅探
  • turn_loop 构建请求前对消息克隆物化;重试/会话恢复重新读文件,原图丢失明确报错,不静默丢图
  • Anthropic:data URL 拆分为原生 source:{type:"base64",media_type,data};OpenAI Chat/Responses 补请求体契约测试
  • 日志/transcript/context inspector/compaction 全线 [image:mime,N bytes] 占位,Base64 不出请求外
  • image_analyze 加固:独立大小上限、魔数嗅探、工具描述明确"仅用于未随消息提供的图片"、去除硬编码 temperature(kimi-for-coding 等限制性模型从必然 400 变为可用)

验证

  • cargo check -p codewhale-tui 通过
  • 33 个图片相关测试全过:三家 provider 请求 JSON 契约、路径逃逸、缺文件报错、持久化无 Base64、伪造扩展名拒绝
  • cargo test forkguard_ 33 项全过(含新增 4 项)

备注

  • 配套父仓 PR(Pinvou/pinvou-agent 的 feat/native-image-input)已按 fork-policy §3 同 PR 携带 fork-modifications.md 登记与 fork-guard.sh 指纹
  • 建议用 merge commit 合并:父仓 gitlink 已指向本提交 d4a05585e;squash 会改变哈希,父仓需再追加一次 gitlink 更新
  • 本能力属通用能力,后续可按 fork-policy §2 评估精简后提上游

- Op::SendMessage 新增可选结构化输入 UserMessageInput(Text/LocalImage),纯文本路径行为不变
- ContentBlock 新增 LocalImage 本地图片引用,会话持久化只存 workspace 相对路径与元数据,不存 Base64
- turn loop 构建 provider 请求前对消息克隆物化:workspace 相对路径校验、20MB 上限、魔数 MIME 嗅探,文件缺失明确报错
- Anthropic 遇 data: URL 转换为原生 base64 source;Chat/Responses 图片块序列化补契约测试
- 收口 Base64 泄漏面:mouse_ui 占位渲染、runtime_api 返回 metadata、context_report 固定估算
- image_analyze 加固:20MB 上限、真实文件头检测、更新工具描述(仅用于未随当前消息原生提供的图片)
- image_analyze 请求不再携带 temperature:kimi-for-coding 等模型只接受默认值,显式 temperature 会被 400 拒绝

Signed-off-by: luzeyang (INT) <lu.zeyang@h3c.com>
@github-actions

Copy link
Copy Markdown

Thanks @qiuYliangM for taking the time to contribute.

This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered.

Please read CONTRIBUTING.md for the expected contribution shape. A maintainer can grant recurring PR access by commenting /lgtm on a pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant