Initial TrueGrowth source import

This commit is contained in:
2026-07-07 09:36:36 +08:00
commit 3b6781d695
2283 changed files with 691996 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
## Context
当前仓库中已经存在统一的 `GeminiMessage` 消息结构,并且底层协议层已经能处理图片消息:
- `openai.chat.completions` 可以直接承载 `image_url`
- `google.generateContent` 已经能把 `image_url` 转成 `inline_data`
但上层文本链路并没有把图片喂给协议层:
- `chat-service` 会显式丢弃 `attachments`
- `AgentExecutor` 默认只发送结构化文本和图片占位符
- `ai_analyze` 工作流主要传递纯文本 `messages`
因此,当前需要解决的不是“协议是否支持图片”,而是“什么时候允许文本消息带图,以及如何在不同入口统一组装消息”。
## Goals / Non-Goals
- Goals:
- 让文本聊天与 Agent 在支持的绑定上能真正发送图片内容
- 用绑定能力位控制是否允许图片输入,避免纯文本模型误收图片
- 在不改动现有 provider routing 主干的前提下复用现有 `GeminiMessage` 结构
- Non-Goals:
- 不在本阶段接入新的文件上传协议
- 不在本阶段统一支持所有第三方自定义文本协议
- 不在本阶段做服务端中转上传
## Decisions
### Decision: 以绑定能力位控制文本图片输入
文本模型是否支持图片输入,不再由 UI 或模型名猜测,而是由文本绑定显式声明。
建议新增字段:
```ts
interface TextInputCapability {
supportsImageInput?: boolean;
maxImageCount?: number;
}
```
第一阶段默认规则:
- `google.generateContent` 绑定默认 `supportsImageInput = true`
- `openai.chat.completions` 绑定默认 `supportsImageInput = true`
- 其他文本绑定默认 `false`
这样可以在不引入复杂供应商探测的前提下,先覆盖当前已经落地的两条文本协议。
### Decision: 统一使用 `GeminiMessage.content[]` 承载文本图片消息
不新增新的消息结构,继续复用:
```ts
type GeminiMessagePart =
| { type: 'text'; text: string }
| { type: 'image_url'; image_url: { url: string } };
```
原因:
- 现有 OpenAI 兼容消息已经能直接使用 `image_url`
- 现有 Google 协议转换器已经能把 `image_url` 转成 `inline_data`
- 这条路径对聊天与 Agent 都可复用
### Decision: 先优先支持可直接引用的图片来源
第一阶段支持以下来源:
- 聊天抽屉上传得到的图片附件
- 画布分析/Agent 选择上下文中的图片 URL
- 已存在的 `data:`、缓存 URL、远程 URL
对于 Google 协议,继续依赖现有 `toGoogleInlineData()` 在发送前转码。
### Decision: 保留参考图片占位说明,但不再仅靠占位符
Agent 原有的“参考图片说明文字”仍可保留,帮助模型理解上下文,但它不应代替真实图片输入。
最终消息结构应同时包含:
- 文本说明
- 图片内容 part
## Risks / Trade-offs
- 第三方 OpenAI 兼容供应商未必真的支持 vision即使接口名是 `chat/completions`
- Mitigation: 第一阶段仍以绑定能力位控制,必要时允许后续做供应商级覆盖
- 将本地图片转为 `data:` 或 Google `inline_data` 可能增大请求体
- Mitigation: 第一阶段不处理超大图上传,后续通过 Gemini Files API / OpenAI file 引用扩展
- Agent 消息结构从纯文本变成多 part 后,旧的日志和调试输出可能不再完整反映实际请求
- Mitigation: 为消息组装层增加最小调试信息与测试覆盖
## Migration Plan
1. 为文本 binding 增加图片输入能力声明与推断
2. 改造聊天服务,允许在支持的文本 binding 下发送附件图片
3. 改造 Agent 默认执行链,将参考图片拼进用户消息
4. 改造 `ai_analyze` 相关入口,透传图片内容而不是只透传占位符
5. 补充最小测试,覆盖 OpenAI 与 Google 两条路径
## Open Questions
- 是否需要在 UI 上对“当前文本模型支持看图”做显式提示
- 第三方自定义文本协议是否需要在设置页允许手动关闭 vision 能力

View File

@@ -0,0 +1,51 @@
# Change: 为文本与 Agent 增加图片理解能力
## Why
当前项目中的图片与视频生成链已经支持多供应商协议路由,但文本与 Agent 链路仍然只把图片作为“存在附件”或“占位符说明”处理,没有真正把图片内容发送给上游模型。
这导致用户在聊天抽屉、AI 分析、Agent 工具规划等场景中,无法直接让模型“看图理解”,也无法在保持现有多供应商路由的前提下,安全地区分哪些文本模型支持图片输入、哪些不支持。
## What Changes
- 为文本协议绑定增加“支持图片输入”的能力声明
- 在聊天抽屉文本发送链中,将附件图片按多模态消息内容发送,而不是统一丢弃
- 在 Agent / `ai_analyze` 链中,将参考图片作为真实图片内容发送,而不是仅传占位符文本
- 第一阶段仅覆盖当前最稳定的两类文本协议:
- `openai.chat.completions`
- `google.generateContent`
- 为不支持图片输入的文本绑定增加显式保护,避免把图片内容发送给纯文本模型
- 保持现有文本、图片、视频的 provider routing 结构不变,不在本变更中引入新的上传协议或文件存储后端
## Impact
- Affected specs:
- `agent-image-understanding`
- Affected code:
- `packages/drawnix/src/services/chat-service.ts`
- `packages/drawnix/src/services/agent/agent-executor.ts`
- `packages/drawnix/src/components/ai-input-bar/workflow-converter.ts`
- `packages/drawnix/src/services/canvas-operations/ai-analyze.ts`
- `packages/drawnix/src/mcp/tools/ai-analyze.ts`
- `packages/drawnix/src/services/provider-routing/*`
- `packages/drawnix/src/utils/gemini-api/*`
## Scope
### Included In This Change
- 聊天抽屉中的附件图片进入文本消息
- Agent 默认执行链中的参考图片进入文本消息
- `ai_analyze` 工作流与画布分析场景中的参考图片进入文本消息
- 绑定级图片输入能力控制
### Not Included In This Change
- Gemini Files API 大文件上传
- OpenAI `responses` 协议接入
- 新增文件持久化后端或服务端中转
- 文本模型能力的自动远程探测
## Relationship To Existing Changes
- 本变更建立在 `add-provider-protocol-routing` 的文本协议绑定与运行时规划之上
- 本变更复用 `add-ai-input-paste-images` 已经建立的输入图片获取链路,但扩展其在文本/Agent 场景中的消费方式

View File

@@ -0,0 +1,55 @@
## ADDED Requirements
### Requirement: Text Bindings Declare Image Understanding Capability
The system SHALL determine whether a text invocation can accept image input from the resolved text binding, instead of assuming every text model supports multimodal input.
#### Scenario: Supported text binding accepts image input
- **GIVEN** a text invocation resolves to a binding whose protocol supports image input
- **WHEN** the user sends a text request with one or more images
- **THEN** the system SHALL allow those images to be included in the outbound text request
#### Scenario: Unsupported text binding stays text-only
- **GIVEN** a text invocation resolves to a binding that does not support image input
- **WHEN** the user sends a text request with one or more images
- **THEN** the system SHALL NOT include image parts in the outbound request
- **AND** SHALL preserve the existing text-only behavior for that invocation
### Requirement: Chat Messages Can Carry Attached Images To Supported Text Models
The system SHALL allow chat messages to include attached images when the resolved text binding supports image understanding.
#### Scenario: Chat drawer sends attached image to OpenAI-compatible text protocol
- **GIVEN** the user attaches an image in the chat drawer
- **AND** the selected text binding resolves to `openai.chat.completions`
- **WHEN** the user sends the message
- **THEN** the outbound message SHALL include the user text and the attached image as multimodal message parts
#### Scenario: Chat drawer sends attached image to Google text protocol
- **GIVEN** the user attaches an image in the chat drawer
- **AND** the selected text binding resolves to `google.generateContent`
- **WHEN** the user sends the message
- **THEN** the outbound request SHALL include the user text and image content
- **AND** the image SHALL be converted into the Google-compatible payload shape before submission
### Requirement: Agent And AI Analyze Requests Preserve Real Reference Images
The system SHALL preserve real image inputs for Agent and AI analyze requests instead of reducing them to placeholder text only.
#### Scenario: Default Agent execution sends reference images
- **GIVEN** the Agent context contains one or more selected images
- **WHEN** the Agent builds the default user request
- **THEN** the request SHALL include the structured text prompt
- **AND** SHALL also include the selected images as message parts when the resolved text binding supports image input
#### Scenario: AI analyze workflow keeps image content across conversion
- **GIVEN** an `ai_analyze` workflow step is created from a request containing reference images
- **WHEN** that step is executed later
- **THEN** the workflow path SHALL preserve the reference image content needed for text-model image understanding
- **AND** SHALL not rely only on placeholder text to represent those images

View File

@@ -0,0 +1,26 @@
# Tasks: 文本与 Agent 图片理解能力
## 1. 绑定能力
- [x] 1.1 为文本协议绑定增加图片输入能力字段
- [x] 1.2 为 `google.generateContent``openai.chat.completions` 推断默认图片输入能力
- [x] 1.3 为不支持图片输入的文本绑定保留安全默认值
## 2. 聊天抽屉文本链
- [x] 2.1 改造 `chat-service`,在支持的文本绑定上将附件图片组装为 `image_url` parts
- [x] 2.2 保持不支持图片输入的文本模型现有文本行为不变
- [x] 2.3 复用现有图片预处理与 URL 处理逻辑,避免新增平行实现
## 3. Agent 与 AI 分析链
- [x] 3.1 改造 `AgentExecutor` 默认消息组装逻辑,发送真实参考图片内容
- [x] 3.2 改造 `ai_analyze` 相关入口,确保图片内容在工作流路径中被保留
- [x] 3.3 保留原有参考图片说明文字,但不再仅依赖占位符
## 4. 验证
- [x] 4.1 补充文本多模态消息组装测试
- [x] 4.2 验证 OpenAI 文本协议可接收图片 part
- [x] 4.3 验证 Google 文本协议可将图片 part 转为 `inline_data`
- [x] 4.4 验证不支持图片输入的文本绑定不会发送图片内容