kit初版,模型引入,agent优化

This commit is contained in:
2026-04-13 00:41:23 +08:00
parent 9b053e302b
commit c435ab15cf
14097 changed files with 5032 additions and 2676248 deletions

View File

@@ -4,6 +4,356 @@
## 记录
### [CL-20260413-0800] 2026-04-13 08:00 — 修复 InstantStyle ReadTimeout + 多次生成丢失参考图
- **tags**: bug修复, Replicate, InstantStyle, timeout, 参考图, Agent Loop, wait, SDK
- **affected_files**:
- art-agent/backend/app/services/image_gen.py
- art-agent/backend/app/agent/loop.py
- **what**: 修复 InstantStyle 首次调用 ReadTimeout (61.4s) + 后续调用丢失参考图返回 "No input, Save money"
- **why**: 两个运行时日志证实的独立问题:(1) `wait=60` 时 SDK `_create_prediction_timeout` 生成 `httpx.Timeout(5.0, read=60.5)` 作为 per-request timeout 传给 `httpx.AsyncClient.request()`,优先级高于客户端级 300s timeout(2) 成功生成后执行 `ref_image_url = None`,但 LLM 可能在后续轮次继续调用工具,此时 InstantStyle 因没有 `style_image` 返回 "No input, Save money"
- **decisions**: (1) `wait=60``wait=False`:不发 `Prefer: wait` headercreate 请求立即返回 prediction IDSDK 自动进入 `prediction.async_wait()` 轮询路径。轮询请求不带 per-request timeout使用客户端级 `read=300s`。代价:比 `Prefer: wait` 模式多几秒轮询延迟,但绝不会 timeout。(2) 完全移除 `ref_image_url = None`:消息构建(附加参考图到 LLM 消息在外层循环前一次性完成不受影响。ref_image_url 只在 `execute_tool()` 中使用,整个对话期间都应该传递
- **notes**: 迭代了 CL-0700 和 CL-0730 的方案。wait 参数完整语义:`True` = `Prefer: wait` + read=60.5s`int(n)` = `Prefer: wait={n}` + read={n+0.5}sn 必须 1-60`False` = 不等待、纯轮询。对慢模型InstantStyle ~128s配合大 payload1.6MB base64`wait=False` 是唯一可靠选项
### [CL-20260413-0730] 2026-04-13 07:30 — 修复生图失败后 LLM 重试丢失参考图
- **tags**: bug修复, Agent Loop, 参考图, InstantStyle, ref_image_url
- **affected_files**:
- art-agent/backend/app/agent/loop.py
- **what**: 修复 LLM 第一次生图工具调用失败后重试时参考图丢失InstantStyle 返回 "No input, Save money"
- **why**: `loop.py` 在每轮工具调用循环结束后无条件执行 `ref_image_url = None`。当第一次调用超时失败后LLM 决定重试,但此时 ref_image_url 已被清空第二次工具调用没有参考图。InstantStyle 模型必须有 `style_image` 才能工作
- **decisions**: 改为条件性清除:在工具调用循环中标记 `tc_data["_had_images"] = True`,循环结束后检查是否有任何成功产出,只有 `any_success` 时才清除 ref_image_url。失败时保留参考图供后续重试
- **notes**: 这个改动对所有参考图模型生效Kolors、InstantStyle 等。只要本轮所有工具调用都失败了ref_image_url 会一直保留直到某次成功为止
### [CL-20260413-0700] 2026-04-13 07:00 — 修复 InstantStyle 生图 422 + ReadTimeoutwait 参数超限与 SDK 内部 timeout 覆盖
- **tags**: bug修复, Replicate, InstantStyle, API参数, async_run, Prefer header, timeout
- **affected_files**:
- art-agent/backend/app/services/image_gen.py
- **what**: 修复 InstantStyle 生图 422`Prefer: wait=x must be 1-60`)和后续 ReadTimeout61.4s 超时)
- **why**: 上次修超时时将 `async_run(wait=300)` 设为 300 秒。Replicate SDK 将 int 类型的 wait 值设为 `Prefer: wait=300` header → API 返回 422。改为 `wait=True` 后 SDK 生成内部 `httpx.Timeout(read=60.5)` 作为请求级 timeout 覆盖了客户端级 300s timeout → 上传 1.6MB base64 style_image + 等待响应超过 60s → ReadTimeout
- **decisions**: 最终改为 `wait=60`API 允许的最大 int 值。SDK 行为:(1) `Prefer: wait=60` header合法(2) 内部 timeout `read=60.5s` 用于初始 create prediction 请求;(3) 60s 内未完成自动 fallback 到 `prediction.async_wait()` 轮询;(4) 轮询请求用客户端级 `httpx.Timeout(read=300s)`
- **notes**: Replicate SDK wait 参数语义:`True` = `Prefer: wait` + read=60.5s`int(n)` = `Prefer: wait={n}` + read={n+0.5}sn 必须 1-60`False` = 不等待。对慢模型用 `wait=60` + 长客户端 timeout 是最优组合
### [CL-20260413-0630] 2026-04-13 06:30 — 修复 Replicate SDK 不走代理 + 超时:自定义 Client 注入代理和长超时
- **tags**: bug修复, Replicate, InstantStyle, 代理, httpx, 超时, 图像生成
- **affected_files**:
- art-agent/backend/app/services/image_gen.py
- **what**: 修复 InstantStyle 调用时 ConnectTimeout / ReadTimeout + "URL missing protocol" 连环错误
- **why**: Replicate Python SDK 的 `_build_httpx_client` 显式传入 `transport=AsyncHTTPTransport()`,导致 httpx 跳过环境变量中的 `HTTPS_PROXY` 代理配置直连 Replicate API。网络不稳定时直连超时SDK 内部状态异常导致后续请求报 "URL missing protocol"。同时默认 read timeout 30s 不够 InstantStyle 的 ~128s 生成时间
- **decisions**: 创建 `_make_replicate_client()` 工厂函数,从环境变量读取代理并注入到 `AsyncHTTPTransport(proxy=...)` 中传给 `ReplicateClient`。read timeout 300s、connect timeout 30s。`_download_image` 也加了代理和 60s 超时
- **notes**: Replicate SDK 的代理绕过是个已知设计缺陷(显式 transport 覆盖了 httpx 的代理自动检测)。此修复对所有通过 `_replicate_client` 的 Replicate API 调用生效。无代理环境下也兼容(`proxy=None` 时 httpx 不走代理)
### [CL-20260413-0600] 2026-04-13 06:00 — 新增 InstantStyle 模型:强风格迁移选项
- **tags**: 模型注册, InstantStyle, 风格迁移, IP-Adapter, 模型配置
- **affected_files**:
- art-agent/backend/app/config.py
- **what**: 在模型注册表中新增 InstantStyle`jyoung105/instant-style`),专门做风格分离迁移,与 Kolors IP-Adapter 并列为两个参考图模型选项
- **why**: Kolors IP-Adapter 的风格迁移弱(内容+风格+构图混合提取),经调研 InstantStyle 是 Replicate 上风格迁移能力最强的可用模型,能从参考图中分离出纯画风(线条、着色、色调)
- **decisions**: 利用现有 `supports_ref_image` + `ref_image_param` 抽象机制InstantStyle 的 `style_image` 参数名通过配置映射,无需修改 `_build_input` 逻辑。默认 `block_mode: "style-only"`(只迁移风格不迁移构图),`style_strength: 1.0`
- **notes**: InstantStyle 较贵(~$0.12/次)且慢(~128s适合风格定调阶段使用Kolors 保留为低成本快速测试选项。社区模型需版本 hash
### [CL-20260413-0540] 2026-04-13 05:40 — 非 vision LLM + 参考图时禁止猜测风格,避免 prompt 与参考图风格冲突
- **tags**: prompt 工程, IP-Adapter, 风格一致性, system prompt, 非vision模型
- **affected_files**:
- art-agent/backend/app/agent/loop.py
- **what**: 修改 system prompt 和非 vision 模型的参考图文字提示,明确要求 LLM 不要猜测/指定画风关键词,风格完全交给 IP-Adapter 从参考图提取
- **why**: DeepSeek 等非 vision LLM 看不到参考图内容,会根据"2D 游戏"等关键词脑补风格(如 pixel art导致 prompt 中的风格描述与参考图实际风格严重冲突。IP-Adapter 优先服从 prompt 的显式风格指令,参考图的风格影响被稀释
- **decisions**: 双重约束——system prompt 中加入"看不到参考图时不猜风格"的通用指引 + 注入的文字提示中用编号列表明确三条规则。保留了 vision 模型路径不变vision 模型能看图,可以写风格词)
- **notes**: 这是过渡方案,等切换到 vision LLM如 GPT-4oLLM 可直接看图描述风格,此约束自动失效(走 vision_capable 分支)
### [CL-20260413-0520] 2026-04-13 05:20 — 多图生成改为单次 API 调用 + 修复空错误信息
- **tags**: 性能优化, Replicate, 速率限制, 错误处理, 模型配置
- **affected_files**:
- art-agent/backend/app/services/image_gen.py
- art-agent/backend/app/config.py
- **what**: 多图生成从 for 循环多次 API 调用改为单次调用(利用模型原生批量参数),同时修复异常 str() 为空时的错误信息丢失
- **why**: LLM 传 num_images=3 时会发 3 个独立 API 请求在低余额账户的严格速率限制burst=1下后续请求会被 429 拦截。改为单次调用后只消耗 1 次请求配额。空错误信息(`[生成失败: ]`)导致用户无法诊断失败原因
- **decisions**: 新增 `num_images_param` 配置字段Flux 用 `num_outputs`Kolors 用 `number_of_images`),由 `_build_input` 统一注入。从 kolors 的 default_params 中移除了硬编码的 `number_of_images: 1`,改为动态设置
- **notes**: 空异常现在显示为 `{TypeName}: {repr(e)}`,确保始终有诊断信息
### [CL-20260413-0500] 2026-04-13 05:00 — 生成图片后显示使用的模型名称
- **tags**: 模型溯源, SSE, 图片生成, 前端展示
- **affected_files**:
- art-agent/backend/app/services/image_gen.py
- art-agent/backend/app/agent/tools.py
- art-agent/backend/app/agent/loop.py
- art-agent/frontend/src/lib/types.ts
- art-agent/frontend/src/app/page.tsx
- art-agent/frontend/src/components/chat/chat-messages.tsx
- **what**: 图片生成后在对话中显示实际使用的模型名称(如"由 Kolors IP-Adapter 生成"),失败时也附带模型名称
- **why**: 用户无法确认前端选择的模型是否真的被用于生图,特别是在多模型切换场景下需要明确溯源
- **decisions**: `generate_images` 返回值从 `list[str]` 改为 `GenerateResult` 数据类(包含 urls + model_name + model_id模型名称通过 SSE `image_result``tool_error` 事件透传到前端。ChatMessage 类型新增 `modelName` 可选字段,消息归档后仍可查看模型来源
- **notes**: 模型名称来自 config.py 注册表中的 `name` 字段,所以显示的是友好名称而非 Replicate 的 model_id
### [CL-20260413-0440] 2026-04-13 04:40 — 修复 Kolors IP-Adapter 模型 404 错误:补全 Replicate 版本 hash
- **tags**: bug修复, Replicate, Kolors, IP-Adapter, 模型配置
- **affected_files**:
- art-agent/backend/app/config.py
- **what**: 在 kolors-ipadapter 的 model_id 中补全版本 hash`fofr/kolors-with-ipadapter` 改为 `fofr/kolors-with-ipadapter:5a1a92b2...`
- **why**: Replicate SDK `async_run` 对非 official 模型(社区模型)只用 `owner/model` 格式调用时,会尝试 official model predictions 端点,该端点返回 404。必须使用 `owner/model:version_hash` 格式才能正确创建 prediction
- **decisions**: 只修复 kolors 模型唯一报错的其他三个模型flux-schnell、flux-dev、sdxl均为 official/热门模型,`owner/model` 格式能正常工作
- **notes**: 未来新增社区模型时,需确保 model_id 包含版本 hash。经实测加版本 hash 后生图成功
### [CL-20260413-0430] 2026-04-13 04:30 — 图片生成失败时将具体错误信息透传到前端
- **tags**: 错误处理, Agent Loop, SSE, 调试体验
- **affected_files**:
- art-agent/backend/app/agent/loop.py
- art-agent/frontend/src/app/page.tsx
- art-agent/frontend/src/lib/api.ts
- **what**: 新增 `tool_error` SSE 事件类型,将图片生成工具的具体错误信息(如 Replicate API 报错详情)直接透传到前端展示
- **why**: 之前工具调用失败时,错误信息只传回给 LLMLLM 会自行"翻译"错误(如说成"速率限制"),用户无法看到真实报错,排查困难。典型场景:使用 Kolors IP-Adapter 生图失败,前端只看到 LLM 的模糊描述,无法定位是参数错误、超时还是 API 限制
- **decisions**: 错误信息同时发给前端展示和 LLM 继续对话,不互斥。前端用 ⚠️ 前缀醒目显示错误详情
- **notes**: 此改动不影响 LLM 的重试机制(工具结果仍然回传给 LLM只是额外增加了一条面向用户的 SSE 事件
### [CL-20260413-0330] 2026-04-13 03:30 — README 补充访问地址汇总 + 穿透管理文档
- **tags**: 文档, README, 穿透, Cloudflare, cloudflared
- **affected_files**:
- art-agent/README.md (新增"访问地址"章节 + 重写"远程访问"章节)
- **what**: README 新增三种访问场景(本机/局域网/外网)的地址汇总表,重写远程访问章节补充 cloudflared 安装指引、穿透管理操作表、代理配置排错
- **why**: 原 README 远程访问章节过于简略,缺少 cloudflared 安装方式、穿透的启动/停止/排错说明,用户实际操作时需要这些信息
- **decisions**:
- 访问地址章节放在"使用"之后、"配置说明"之前,让用户启动后立即看到访问方式
- cloudflared 安装提供 winget 和手动下载两种方式winget 安装后可能不在 PATH 中)
- 穿透管理用表格呈现(启动/停止/查看状态/重启),简洁直观
- 代理排错放在注意事项中,因为国内环境常需代理才能连上 Cloudflare
- **notes**: 无
### [CL-20260412-2345] 2026-04-12 23:45 — 参考图上传独立化:进度条 + 状态反馈 + 失败重试
- **tags**: 前端, 后端, 参考图, 上传, UX, 进度反馈
- **affected_files**:
- art-agent/backend/app/api/chat.py (新增 POST /api/upload-ref-image 独立上传端点chat 端点新增 ref_image_url 字段)
- art-agent/frontend/src/lib/api.ts (新增 uploadRefImage 函数XMLHttpRequest 实现进度回调sendChat 参数从 File 改为服务端路径字符串)
- art-agent/frontend/src/components/chat/chat-input.tsx (重写上传流程选图即上传、环形进度条、状态角标、失败重试、input value 重置)
- art-agent/frontend/src/app/page.tsx (handleSend 适配新签名:接收服务端路径而非 File标注截图也走独立上传)
- **what**: 将参考图从"随消息一起提交"改为"选中后立即独立上传",全程有进度条、状态提示、失败重试入口
- **why**: 原方案图片上传绑定在发送消息时才执行,无任何进度反馈。大图或走 Cloudflare Tunnel 时用户完全无法判断上传是否开始、是否成功、是否卡住。多次上传参考图后 file input 不重置也导致交互异常
- **decisions**: 使用 XMLHttpRequest 而非 fetchfetch 不支持 upload progress 事件);后端同时保留 ref_image 文件上传和 ref_image_url 路径两种方式,向后兼容
- **notes**: 上传超时设为 120 秒;支持 AbortController 取消file input 每次选择后立即重置 value确保同一文件可重复选择
### [CL-20260412-2315] 2026-04-12 23:15 — 修复 Cloudflare Tunnel 跨域开发警告
- **tags**: 前端, 配置, Next.js, Cloudflare, 跨域
- **affected_files**:
- art-agent/frontend/next.config.ts (新增 allowedDevOrigins)
- **what**: 在 next.config.ts 中添加 `allowedDevOrigins: ["*.trycloudflare.com"]`,消除 Cloudflare Tunnel 穿透时的跨域警告
- **why**: Next.js 检测到来自 trycloudflare.com 的跨域请求,发出警告提示未来版本将强制要求配置
- **decisions**: 使用通配符 `*.trycloudflare.com` 覆盖所有 Quick Tunnel 随机域名
- **notes**: 仅影响开发模式,生产构建不受影响
### [CL-20260412-2300] 2026-04-12 23:00 — 集成 Kolors IP-Adapter 模型,参考图可直接用于风格生成
- **tags**: 后端, 前端, IP-Adapter, 风格迁移, 参考图, 模型注册, Replicate, 架构
- **affected_files**:
- art-agent/backend/app/config.py (新增 kolors-ipadapter 模型注册 + supports_ref_image / ref_image_param 通用字段)
- art-agent/backend/app/services/image_gen.py (ReplicateProvider._build_input 支持参考图注入 + to_data_uri 公共工具函数)
- art-agent/backend/app/agent/loop.py (复用 to_data_uri 替代原 _to_vision_url移除冗余 import)
- art-agent/frontend/src/lib/types.ts (ImageModelInfo 新增 supports_ref_image 字段)
- art-agent/frontend/src/components/chat/model-selector.tsx (模型列表中显示"参考图"标记)
- **what**: 集成 Kolors IP-Adapter 模型fofr/kolors-with-ipadapter参考图可真正参与图像生成的风格控制架构上为后续切换其他 IP-Adapter 模型预留了通用扩展机制
- **why**: 之前参考图仅由 LLM 侧理解(且 DeepSeek 看不到图),生图工具侧完全忽略了参考图。用户希望参考图能真正影响生成结果的风格
- **decisions**:
- 模型注册表新增两个通用字段supports_ref_image布尔标记和 ref_image_param参考图参数名不同模型可能不同
- _build_input 根据 supports_ref_image 自动走不同构建逻辑,新增 IP-Adapter 模型只需加注册表配置
- 参考图通过 base64 data URI 传递给 Replicate避免本地 URL 不可达的问题)
- to_data_uri 抽为 image_gen.py 中的公共函数loop.py 复用(替代原 _to_vision_url
- Kolors IP-Adapter 默认 ip_adapter_weight=0.8(非 1.0),给 prompt 文字留一些影响空间
- 前端模型列表中为支持参考图的模型显示绿色"参考图"徽章
- get_image_models_list 返回 supports_ref_image 字段,前端据此渲染标记
- **notes**:
- Kolors IP-Adapter 成本极低(~$0.004/次),速度快(~4s
- 后续要换其他 IP-Adapter 模型(如 Flux IP-Adapter v2只需在 IMAGE_MODELS 中新增配置
- 分层组合产线方案IP-Adapter → LoRA → ControlNet已记录为延期方案 [style-pipeline-layered]
### [CL-20260412-2230] 2026-04-12 22:30 — 用户消息气泡中显示参考图缩略图
- **tags**: 前端, 参考图, UX, chat-messages
- **affected_files**:
- art-agent/frontend/src/lib/types.ts (ChatMessage 新增 refImageUrl 字段)
- art-agent/frontend/src/app/page.tsx (构造 userMessage 时保存参考图 Blob URL)
- art-agent/frontend/src/components/chat/chat-messages.tsx (用户消息气泡中渲染参考图缩略图)
- **what**: 用户上传参考图发送后,在聊天气泡中显示参考图缩略图,让用户确认图片确实被附带发送了
- **why**: 之前用户上传参考图后,发送消息后气泡中看不到参考图,无法确认是否上传成功,体验不好
- **decisions**:
- 使用 URL.createObjectURL 创建 Blob URL 用于当前会话内显示(轻量、即时)
- Blob URL 不持久化到 localStorage刷新后失效避免存储 base64 data URI 的空间开销
- 参考图缩略图显示在消息文本上方,最大尺寸 160×120px
- **notes**:
- Blob URL 仅在当前标签页有效刷新页面后旧消息中的参考图缩略图不可见MVP 可接受)
- 如需持久化,后续可改为存储后端上传路径(需要等后端返回 upload URL 后再构造 userMessage
### [CL-20260412-2200] 2026-04-12 22:00 — 修复 DeepSeek 不支持 image_url 导致参考图上传报错
- **tags**: bug修复, 后端, Agent Loop, vision, DeepSeek, 多模态
- **affected_files**:
- art-agent/backend/app/agent/loop.py (新增 vision 能力检测,非 vision 模型走文字提示)
- **what**: 修复使用 DeepSeek 作为 LLM 时,上传参考图后报 400 错误 `unknown variant 'image_url', expected 'text'`
- **why**: 代码原本假设所有 LLM 都支持 OpenAI Vision API 的 `image_url` content type但 DeepSeek 的 Chat API 只支持 `text` 类型
- **decisions**:
- 通过模型名称关键词检测 vision 能力gpt-4o / gpt-4-vision / claude 视为支持)
- 不支持 vision 的模型:用文字提示告知 LLM 有参考图存在,参考图仍由图像生成工具侧处理
- 支持 vision 的模型:保持原有 image_url 格式不变
- **notes**:
- 此方案确保参考图功能在任何 LLM 下都不会报错
- 非 vision 模型无法"看到"参考图,但生图工具仍会收到参考图用于 img2img 场景
- 如需更精确的 vision 能力检测,可后续改为在 config.py 中按模型注册 vision 标志
### [CL-20260412-2130] 2026-04-12 21:30 — 修复图片生成失败时前端显示破碎图标
- **tags**: bug修复, 前端, 后端, 图像生成, 错误处理
- **affected_files**:
- art-agent/backend/app/agent/tools.py (分离有效 URL 和错误信息)
- art-agent/frontend/src/app/page.tsx (过滤无效 URL空列表时不渲染图片网格)
- **what**: 修复 Replicate API 失败时前端出现 4 个破碎图标框的问题
- **why**: 用户在 Replicate 余额不足402时生图错误字符串被当作图片 URL 传给 `<img>` 标签
- **decisions**:
- 后端 tools.py将 generate_images 返回值分为 images有效 URL和 errors错误信息两个字段
- 前端 page.tsx过滤以 `[` 开头的无效 URL无有效图片时直接 break 不创建 ImageAsset
- **notes**:
- 根因是 Replicate 账户余额不足,需用户到 https://replicate.com/account/billing#billing 充值
- 此修复确保任何 API 错误场景下前端都不会显示破碎图标
### [CL-20260412-2100] 2026-04-12 21:00 — 生图模型动态切换Provider 抽象 + 前端模型选择器
- **tags**: 后端, 前端, 图像生成, 模型切换, Provider, 重构, Replicate
- **affected_files**:
- art-agent/backend/app/config.py (新增 IMAGE_MODELS 注册表 + get_image_model_config / get_image_models_list / get_default_image_model_id)
- art-agent/backend/app/services/image_gen.py (重构ImageProvider 抽象基类 + ReplicateProvider 实现 + generate_images 接受 model_id)
- art-agent/backend/app/api/chat.py (新增 GET /api/models 端点 + POST /api/chat 增加 image_model 参数)
- art-agent/backend/app/agent/loop.py (run_agent_loop 增加 image_model 参数透传)
- art-agent/backend/app/agent/tools.py (execute_tool 增加 image_model 参数透传)
- art-agent/backend/.env (IMAGE_MODEL 改为短 ID 格式)
- art-agent/backend/.env.example (同步更新)
- art-agent/frontend/src/lib/types.ts (新增 ImageModelInfo 类型)
- art-agent/frontend/src/lib/api.ts (新增 fetchModels() + sendChat 增加 imageModel 参数)
- art-agent/frontend/src/components/chat/model-selector.tsx (新建:模型选择下拉组件)
- art-agent/frontend/src/components/chat/chat-input.tsx (集成 ModelSelector + onSend 签名扩展)
- art-agent/frontend/src/app/page.tsx (handleSend 透传 imageModel 到 sendChat)
- **what**: 将图像生成服务从 Replicate 硬绑定重构为 Provider 抽象架构,支持 Replicate 上多模型flux-schnell / flux-dev / SDXL按消息粒度切换
- **why**: 用户希望能在对话中随时切换生图模型来对比不同模型的效果
- **decisions**:
- Provider 模式:抽象基类 ImageProvider + 具体实现(当前只有 ReplicateProvider预留 DalleProvider/ComfyUIProvider 等扩展点
- 模型注册表放在 config.py 中Python dict新增模型只需加一条配置
- 前端模型列表由后端 API 驱动GET /api/models不在前端硬编码
- 切换粒度为每条消息级(最灵活),通过 FormData 传递 image_model 参数
- 模型选择持久化到 localStorage作为后续消息的默认值
- Flux 系列使用 aspect_ratio 参数SDXL 使用 width/height 参数,由 ReplicateProvider._build_input 内部分流处理
- **notes**:
- 向后兼容image_model 参数可选,不传时使用 .env 中的默认模型
- .env 中 IMAGE_MODEL 支持短 IDflux-schnell和完整 Replicate IDblack-forest-labs/flux-schnell自动转换
### [CL-20260412-1800] 2026-04-12 18:00 — 移动端适配 + Cloudflare Tunnel 内网穿透
- **tags**: 前端, 响应式, 移动端, 部署, Cloudflare, 穿透, 配置
- **affected_files**:
- art-agent/frontend/src/app/layout.tsx (viewport meta 配置)
- art-agent/frontend/src/app/globals.css (iOS bounce 防护、tap highlight、dvh 支持、遮罩动画)
- art-agent/frontend/src/app/page.tsx (桌面端展开按钮加 hidden md:flex)
- art-agent/frontend/src/app/gallery/page.tsx (网格 gap/列数适配、hover 操作移动端始终可见、选择框可见)
- art-agent/frontend/src/components/sidebar/sidebar.tsx (移动端固定定位抽屉 + 遮罩)
- art-agent/frontend/src/components/layout/top-nav.tsx (新增汉堡菜单按钮、间距微调)
- art-agent/frontend/src/components/detail/image-detail-panel.tsx (移动端全屏 overlay)
- art-agent/frontend/src/components/chat/chat-messages.tsx (气泡宽度 90%、间距收紧)
- art-agent/frontend/src/components/chat/chat-input.tsx (padding 收紧)
- art-agent/frontend/src/components/chat/image-grid.tsx (max-width 适配、操作栏移动端可见)
- art-agent/frontend/src/lib/app-context.tsx (小屏默认折叠侧边栏、切换会话自动收起)
- art-agent/frontend/next.config.ts (trycloudflare.com + replicate.delivery 白名单)
- art-agent/start-tunnel.ps1 (新建:一键穿透脚本)
- art-agent/README.md (新增远程访问章节、uvicorn 加 --host 0.0.0.0)
- **what**: 为实现手机浏览器远程访问完成移动端响应式适配9 个组件)和 Cloudflare Quick Tunnel 穿透方案
- **why**: 用户希望把项目发给自己和朋友在手机上通过浏览器使用
- **decisions**:
- 移动端断点统一用 `md:` (768px),与 Tailwind 默认保持一致
- 侧边栏移动端用 fixed + overlay 抽屉模式,桌面端保持原有 w-0/w-[280px] 切换
- 图片详情面板移动端全屏fixed inset-0不做半屏因为手机屏幕空间有限
- 穿透方案选 Cloudflare Quick Tunnel免费、免注册不选 ngrok有连接限制
- 穿透脚本自动管理 .env.local 的更新和恢复,减少手动操作
- hover 操作在移动端始终显示(无 hover 事件),避免操作不可达
- 路线 B云服务器正式部署记录为延期方案待后续实施
- **notes**:
- 构建验证通过,无 lint 错误
- cloudflared 通过 winget 安装,版本 2025.8.1
- Quick Tunnel 每次启动分配随机域名xxx.trycloudflare.com非固定
- 穿透启动后需重启前端才能读取新的 NEXT_PUBLIC_API_URL
- project-launcher Skill 中的 uvicorn 命令也同步加了 --host 0.0.0.0
### [CL-20260412-1530] 2026-04-12 15:30 — 修复 .env 配置加载时序问题
- **tags**: 后端, bug修复, 配置, dotenv, Python
- **affected_files**:
- art-agent/backend/app/main.py (load_dotenv 前置 + override=True)
- art-agent/backend/app/config.py (模块级常量 → 函数式懒读取)
- art-agent/backend/app/agent/loop.py (引用改为函数调用)
- art-agent/backend/app/services/image_gen.py (引用改为函数调用)
- art-agent/backend/.env (OPENAI_BASE_URL 去掉 /v1)
- **what**: 修复切换 DeepSeek API 后报 "Model Not Exist" 400 错误
- **why**: 用户修改 .env 切换到 DeepSeek但实际发出的请求仍使用默认模型名 gpt-4o-mini
- **decisions**:
- load_dotenv(override=True) 放在 main.py 所有业务 import 之前,确保环境变量在任何模块读取前就位
- config.py 从模块级常量改为函数get_llm_model() 等),避免 import 时求值被固化
- 不使用 lru_cache避免首次调用在 load_dotenv 前就缓存了空值)
- **notes**:
- 根因有两层import 时序config.py 在 load_dotenv 前被 import+ override 默认行为(不覆盖已有环境变量)
- 通过在 uvicorn 同环境中运行 Python 脚本成功复现了 API 调通,证明问题在进程内加载顺序而非 API 本身
- DeepSeek base_url 使用 https://api.deepseek.com不带 /v1与官方文档一致
### [CL-20260412-1500] 2026-04-12 15:00 — 品牌重命名 EPEEKit + API 配置集中化
- **tags**: EPEEKit, 品牌, 配置, 后端, 前端, 重构
- **affected_files**:
- art-agent/frontend/src/app/layout.tsx (title/description)
- art-agent/frontend/src/components/layout/top-nav.tsx (Logo SVG + 品牌名)
- art-agent/frontend/src/app/page.tsx (欢迎文案)
- art-agent/frontend/src/lib/store.ts (localStorage 键名)
- art-agent/frontend/src/app/gallery/page.tsx (下载前缀)
- art-agent/frontend/src/components/detail/image-detail-panel.tsx (下载前缀)
- art-agent/frontend/src/components/chat/image-grid.tsx (下载前缀)
- art-agent/frontend/package.json (项目名)
- art-agent/frontend/package-lock.json (项目名)
- art-agent/backend/app/main.py (FastAPI title)
- art-agent/backend/app/config.py (新建:集中配置)
- art-agent/backend/app/agent/loop.py (引用集中配置)
- art-agent/backend/app/services/image_gen.py (引用集中配置 + 简化重复分支)
- art-agent/backend/.env (重组为分组结构 + 新增 LLM_MODEL/IMAGE_MODEL 等)
- art-agent/backend/.env.example (新建)
- art-agent/README.md (全文更新)
- **what**: 将应用从 "Art Agent" 正式命名为 "EPEEKit",同时将后端所有硬编码的 API/模型配置抽取到 .env 文件,通过 config.py 集中管理
- **why**: 用户要求正式命名应用并希望能方便地切换 LLM 和图像生成模型进行测试
- **decisions**:
- 品牌名全部统一为 "EPEEKit"包括页面标题、Logo、下载文件名、localStorage 键名
- Logo 采用内联 SVG 设计(主题色圆角方块 + A/i 组合),不引入外部图片资源
- API 配置走 .env + config.py 方案(非 settings.py 类模式),保持极简
- 切换 LLM 只需改 .env 中 3 个值OPENAI_BASE_URL + OPENAI_API_KEY + LLM_MODEL
- image_gen.py 中去除了参考图分支的重复代码(两个分支逻辑完全相同)
- **notes**:
- localStorage 键名变更意味着旧数据不会自动迁移MVP 阶段可接受)
- .env 文件中含真实密钥,需确认 .gitignore 覆盖
### [CL-20260412-0300] 2026-04-12 03:00 — 完成交互原型全面重构
- **tags**: art-agent, 前端, 交互设计, 三栏布局, 标签系统, Canvas标注, 资源库, 后端
- **affected_files**:
- art-agent/frontend/src/app/page.tsx (重写)
- art-agent/frontend/src/app/layout.tsx (添加 AppProvider)
- art-agent/frontend/src/app/globals.css (增加样式)
- art-agent/frontend/src/app/gallery/page.tsx (新建)
- art-agent/frontend/src/lib/types.ts (新建:全局类型定义)
- art-agent/frontend/src/lib/store.ts (新建localStorage 持久化存储)
- art-agent/frontend/src/lib/app-context.tsx (新建:全局状态 Context)
- art-agent/frontend/src/lib/api.ts (更新类型兼容)
- art-agent/frontend/src/components/layout/top-nav.tsx (新建)
- art-agent/frontend/src/components/sidebar/sidebar.tsx (新建)
- art-agent/frontend/src/components/sidebar/session-list.tsx (新建)
- art-agent/frontend/src/components/sidebar/tag-filter.tsx (新建)
- art-agent/frontend/src/components/chat/chat-messages.tsx (适配新类型)
- art-agent/frontend/src/components/chat/chat-input.tsx (增加拖拽上传)
- art-agent/frontend/src/components/chat/image-grid.tsx (增加操作栏)
- art-agent/frontend/src/components/detail/image-detail-panel.tsx (新建)
- art-agent/frontend/src/components/detail/annotation-canvas.tsx (新建)
- art-agent/backend/app/agent/loop.py (System Prompt + base64 转换)
- **what**: 从单页对话 MVP 全面重构为完整交互原型,三个 Phase 一次性完成
- **why**: 用户要求完整设计交互原型,通过规划讨论确定了三栏布局 + 标签系统 + 标注 + 资源库的完整方案
- **decisions**:
- 数据持久化使用 localStorageMVP 阶段),后续可迁移到后端数据库
- 全局状态管理使用 React Context + useReducer 模式,不引入第三方状态库
- 标注功能使用原生 Canvas API不引入第三方画板库减少依赖
- 标注坐标使用归一化比例0-1与图片实际分辨率解耦
- 资源库使用 Modal overlay 展示详情,而非独立路由页面
- 标注截图通过 base64 data URI 直接传给 OpenAI Vision后端自动处理本地路径转换
- **notes**:
- 新增 12 个源文件,修改 6 个现有文件,无新依赖引入
- 内置标签 6 个UI、Icon、原画、风格探索、立绘、概念图
- 标注工具 4 种:矩形框选、箭头、自由画笔、文字,含撤销/清除
- 构建验证通过,无 linter 错误
- 未来可优化:标签自动推荐逻辑(当前仅预留接口)、后端会话持久化、图片搜索索引
### [CL-20260411-1500] 2026-04-11 15:00 — 完成美术 Agent 产品决策和技术选型
- **tags**: art-agent, 产品决策, 技术选型, 规划
- **affected_files**: