kit初版,模型引入,agent优化
This commit is contained in:
0
.cursor/changelog/.changelog-ack
Normal file
0
.cursor/changelog/.changelog-ack
Normal 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` header,create 请求立即返回 prediction ID,SDK 自动进入 `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}s(n 必须 1-60);`False` = 不等待、纯轮询。对慢模型(InstantStyle ~128s)配合大 payload(1.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 + ReadTimeout:wait 参数超限与 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`)和后续 ReadTimeout(61.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}s(n 必须 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-4o)后,LLM 可直接看图描述风格,此约束自动失效(走 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**: 之前工具调用失败时,错误信息只传回给 LLM,LLM 会自行"翻译"错误(如说成"速率限制"),用户无法看到真实报错,排查困难。典型场景:使用 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 而非 fetch(fetch 不支持 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 支持短 ID(flux-schnell)和完整 Replicate ID(black-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**:
|
||||
- 数据持久化使用 localStorage(MVP 阶段),后续可迁移到后端数据库
|
||||
- 全局状态管理使用 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**:
|
||||
|
||||
@@ -2,6 +2,28 @@
|
||||
|
||||
最近 ~50 次改动的一句话概要,按时间倒序排列。每次会话自动注入上下文。
|
||||
|
||||
- [CL-20260413-0800] 修复 InstantStyle ReadTimeout + 多次生成丢失参考图:wait 改 False 走纯轮询 + 不再清除 ref_image_url
|
||||
- [CL-20260413-0730] 修复生图失败后 LLM 重试丢失参考图:ref_image_url 改为仅在成功产出图片后才清除
|
||||
- [CL-20260413-0700] 修复 InstantStyle 生图 422 + ReadTimeout:`wait=300` 超限改为 `wait=60`,SDK 超时自动 fallback 轮询
|
||||
- [CL-20260413-0630] 修复 Replicate SDK 不走代理 + 超时不够:注入 HTTPS_PROXY 到 transport + read 300s / connect 30s,解决 ConnectTimeout 连环错误
|
||||
- [CL-20260413-0600] 新增 InstantStyle 模型(强风格迁移),与 Kolors 并列为参考图模型选项,block_mode=style-only
|
||||
- [CL-20260413-0540] 非 vision LLM + 参考图时禁止猜测风格,prompt 只描述内容不写画风,风格交由 IP-Adapter 处理
|
||||
- [CL-20260413-0520] 多图生成改为单次 API 调用(利用模型原生批量参数),避免速率限制 + 修复空错误信息显示
|
||||
- [CL-20260413-0500] 图片生成后在对话中显示实际使用的模型名称(如"由 Kolors IP-Adapter 生成"),便于模型溯源
|
||||
- [CL-20260413-0440] 修复 Kolors IP-Adapter 404 错误:社区模型需 `owner/model:version_hash` 格式,补全版本 hash 后生图成功
|
||||
- [CL-20260413-0430] 图片生成失败时将具体错误信息(Replicate API 报错等)透传到前端展示,新增 tool_error SSE 事件
|
||||
- [CL-20260413-0330] README 补充访问地址汇总(本机/局域网/外网)+ 穿透管理文档(安装/启停/排错)
|
||||
- [CL-20260412-2345] 参考图上传独立化:选图即上传 + 环形进度条 + 成功/失败状态反馈 + 失败重试,后端新增独立上传端点
|
||||
- [CL-20260412-2315] 修复 Cloudflare Tunnel 跨域开发警告:next.config.ts 新增 allowedDevOrigins 通配符
|
||||
- [CL-20260412-2300] 集成 Kolors IP-Adapter 模型:参考图可直接用于风格生成,模型注册表新增通用参考图支持机制
|
||||
- [CL-20260412-2230] 用户消息气泡中显示参考图缩略图:ChatMessage 新增 refImageUrl,发送后在气泡中渲染参考图
|
||||
- [CL-20260412-2200] 修复 DeepSeek 不支持 image_url 参考图上传报错:新增 vision 能力检测,非 vision 模型走文字提示
|
||||
- [CL-20260412-2130] 修复图片生成失败时前端显示破碎图标:后端分离错误信息与有效 URL,前端过滤无效 URL 不渲染空图片
|
||||
- [CL-20260412-2100] 生图模型动态切换:Provider 抽象架构 + 前端模型选择器 + Replicate 多模型(flux-schnell/flux-dev/SDXL)按消息粒度切换
|
||||
- [CL-20260412-1800] 移动端适配 + Cloudflare Tunnel 内网穿透:响应式布局改造(9 个组件)+ 一键穿透脚本 + cloudflared 安装
|
||||
- [CL-20260412-1530] 修复 .env 配置加载时序问题:load_dotenv 前置 + override=True + config.py 改函数式懒读取
|
||||
- [CL-20260412-1500] 品牌重命名 Art Agent → EPEEKit + 后端 API/模型配置集中化到 .env + config.py
|
||||
- [CL-20260412-0300] 完成交互原型全面重构:三栏布局 + 多会话标签系统 + Canvas 标注 + 资源库页面
|
||||
- [CL-20260411-1630] 安装 Node.js v24.14.1 + Python venv + 前后端依赖,后端启动验证通过
|
||||
- [CL-20260411-1600] 从零创建美术 Agent MVP 全部前后端代码(FastAPI + Next.js + Agent Loop + SSE)
|
||||
- [CL-20260411-1500] 完成美术 Agent 产品决策(5 个核心问题)和技术选型(8 个维度)两份文档
|
||||
|
||||
@@ -3,17 +3,108 @@
|
||||
最近 ~10 次改动的摘要记录,按时间倒序排列。
|
||||
当 Agent 检测到当前任务与近期改动相关时自动读取。
|
||||
|
||||
### [CL-20260411-1630] 2026-04-11 — 完成开发环境搭建和依赖安装
|
||||
- **tags**: art-agent, 环境搭建, Node.js, Python
|
||||
- **affected_files**: art-agent/backend/venv/, art-agent/frontend/node_modules/
|
||||
- **summary**: 安装 Node.js v24.14.1(winget)、创建 Python venv 并安装后端依赖、安装前端 npm 依赖。后端启动验证通过。遇到并解决了 OpenAI 延迟初始化、PowerShell && 不支持、脚本执行策略限制等问题。
|
||||
### [CL-20260413-0800] 2026-04-13 — 修复 InstantStyle ReadTimeout + 多次生成丢失参考图
|
||||
- **tags**: bug修复, Replicate, InstantStyle, timeout, 参考图, Agent Loop, wait
|
||||
- **affected_files**: art-agent/backend/app/services/image_gen.py, art-agent/backend/app/agent/loop.py
|
||||
- **summary**: 运行时日志证实两个问题:(1) `wait=60` 时 SDK 内部 `read=60.5s` timeout 覆盖客户端 300s timeout,上传 1.6MB base64 + 等待初始响应超过 60s → ReadTimeout。改为 `wait=False`,create 请求立即返回 prediction ID,SDK 自动走 `prediction.async_wait()` 轮询,轮询用客户端级 read=300s timeout。(2) 成功生成后清除 ref_image_url 导致后续工具调用丢失参考图(InstantStyle 返回 "No input, Save money")。完全移除清除逻辑,ref_image_url 在整个对话期间保持有效。
|
||||
|
||||
### [CL-20260411-1600] 2026-04-11 — 搭建美术 Agent MVP 全部前后端代码
|
||||
- **tags**: art-agent, MVP, 前端, 后端, FastAPI, Next.js, Agent Loop
|
||||
- **affected_files**: art-agent/backend/app/*, , art-agent/frontend/src/*, docs/art-agent/MVP-PLAN.md
|
||||
- **summary**: 从零创建完整 MVP:后端 FastAPI(Agent Loop + Replicate 图像生成 + SSE)+ 前端 Next.js(Chat UI + 参考图上传 + 图片下载 + 暗色主题)。范围刻意最小化:无数据库、无 Skill 机制、无用户认证。Agent Loop 硬编码 system prompt,使用 GPT-4o-mini + flux-schnell。
|
||||
### [CL-20260413-0730] 2026-04-13 — 修复生图失败后 LLM 重试丢失参考图
|
||||
- **tags**: bug修复, Agent Loop, 参考图, InstantStyle, ref_image_url
|
||||
- **affected_files**: art-agent/backend/app/agent/loop.py
|
||||
- **summary**: LLM 第一次生图工具调用失败后重试时,参考图丢失。InstantStyle 返回 "No input, Save money"。根因:`loop.py` 在每轮工具调用结束后无条件清除 `ref_image_url`。修复:改为只在本轮至少有一次成功产出图片时才清除,失败时保留参考图供 LLM 重试。
|
||||
|
||||
### [CL-20260413-0700] 2026-04-13 — 修复 InstantStyle 生图 422 + ReadTimeout:wait 参数超限
|
||||
- **tags**: bug修复, Replicate, InstantStyle, API参数, async_run, timeout
|
||||
- **affected_files**: art-agent/backend/app/services/image_gen.py
|
||||
- **summary**: InstantStyle 生图 422(`Prefer: wait=x must be 1-60`)+ ReadTimeout(61.4s)。两个问题同根因:`async_run(wait=300)` 超出 API 限制,改为 `wait=True` 后 SDK 内部 60.5s timeout 覆盖了客户端 300s timeout。最终改为 `wait=60`(API 最大合法值),初始请求 60s 内未完成则 SDK 自动 fallback 到异步轮询,轮询用客户端级 read=300s timeout。
|
||||
|
||||
### [CL-20260413-0630] 2026-04-13 — 修复 Replicate SDK 不走代理 + 超时不够
|
||||
- **tags**: bug修复, Replicate, InstantStyle, 代理, httpx, 超时
|
||||
- **affected_files**: art-agent/backend/app/services/image_gen.py
|
||||
- **summary**: Replicate SDK 内部显式传 `transport` 给 httpx,绕过了环境变量代理配置导致 ConnectTimeout,且默认 read 30s 不够 InstantStyle 的 ~128s。修复:`_make_replicate_client()` 工厂函数从 `HTTPS_PROXY` 读取代理注入 `AsyncHTTPTransport(proxy=...)`,read 300s / connect 30s。`_download_image` 同步加了代理。
|
||||
|
||||
### [CL-20260413-0600] 2026-04-13 — 新增 InstantStyle 模型:强风格迁移选项
|
||||
- **tags**: 模型注册, InstantStyle, 风格迁移, IP-Adapter
|
||||
- **affected_files**: art-agent/backend/app/config.py
|
||||
- **summary**: 注册 InstantStyle(`jyoung105/instant-style`)到模型注册表,`block_mode: "style-only"` + `style_strength: 1.0`,通过 `ref_image_param: "style_image"` 适配现有抽象。与 Kolors 并列为参考图模型,提供强风格迁移能力。
|
||||
|
||||
### [CL-20260413-0540] 2026-04-13 — 非 vision LLM + 参考图时禁止猜测风格
|
||||
- **tags**: prompt 工程, IP-Adapter, 风格一致性, system prompt
|
||||
- **affected_files**: art-agent/backend/app/agent/loop.py
|
||||
- **summary**: 修改 system prompt 和非 vision 模型的参考图提示,明确禁止猜测画风。LLM 只描述画面内容,风格交给 IP-Adapter 从参考图提取。解决了 DeepSeek 看不到参考图时脑补 "pixel art" 导致生成结果与参考图风格不一致的问题。
|
||||
|
||||
### [CL-20260413-0520] 2026-04-13 — 多图生成改为单次 API 调用 + 修复空错误信息
|
||||
- **tags**: 性能优化, Replicate, 速率限制, 错误处理, 模型配置
|
||||
- **affected_files**: art-agent/backend/app/services/image_gen.py, art-agent/backend/app/config.py
|
||||
- **summary**: 多图生成从 for 循环改为单次 API 调用(新增 `num_images_param` 配置),避免低余额账户的速率限制。同时修复空异常时 `[生成失败: ]` 信息丢失的问题,改为显示异常类型名和 repr。
|
||||
|
||||
### [CL-20260413-0500] 2026-04-13 — 生成图片后显示使用的模型名称
|
||||
- **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
|
||||
- **summary**: `generate_images` 返回 `GenerateResult`(含 model_name),SSE 事件携带模型名称,前端在图片下方和错误提示中展示。ChatMessage 新增 `modelName` 字段,归档后仍可溯源。
|
||||
|
||||
### [CL-20260413-0440] 2026-04-13 — 修复 Kolors IP-Adapter 模型 404 错误:补全 Replicate 版本 hash
|
||||
- **tags**: bug修复, Replicate, Kolors, IP-Adapter, 模型配置
|
||||
- **affected_files**: art-agent/backend/app/config.py
|
||||
- **summary**: Kolors IP-Adapter 生图 404 的根因是 Replicate SDK 对社区模型需要 `owner/model:version_hash` 格式。在 config.py 中补全 kolors-ipadapter 的版本 hash 后,实测生图成功。
|
||||
|
||||
### [CL-20260413-0430] 2026-04-13 — 图片生成失败时将具体错误信息透传到前端
|
||||
- **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
|
||||
- **summary**: 新增 `tool_error` SSE 事件类型。Agent Loop 在工具执行产生错误时,额外 yield 一个 tool_error 事件携带具体报错信息;前端处理该事件并以 ⚠️ 前缀展示在对话流中。解决了之前工具失败时用户只能看到 LLM 模糊翻译、无法获取真实错误详情的问题。
|
||||
|
||||
### [CL-20260413-0330] 2026-04-13 — README 补充访问地址汇总 + 穿透管理文档
|
||||
- **tags**: 文档, README, 穿透, Cloudflare, cloudflared
|
||||
- **affected_files**: art-agent/README.md
|
||||
- **summary**: README 新增"访问地址"章节(本机/局域网/外网三种场景表格),重写"远程访问(外网穿透)"章节,补充 cloudflared 安装指引(winget + 手动下载)、穿透管理操作表(启动/停止/查看状态/重启)、代理配置排错说明。
|
||||
|
||||
### [CL-20260412-2345] 2026-04-12 — 参考图上传独立化:进度条 + 状态反馈 + 失败重试
|
||||
- **tags**: 前端, 后端, 参考图, 上传, UX, 进度反馈
|
||||
- **affected_files**: art-agent/backend/app/api/chat.py, art-agent/frontend/src/lib/api.ts, art-agent/frontend/src/components/chat/chat-input.tsx, art-agent/frontend/src/app/page.tsx
|
||||
- **summary**: 参考图从"随消息提交"改为"选中即独立上传"。后端新增 POST /api/upload-ref-image 端点;前端用 XMLHttpRequest 获取上传进度事件,ChatInput 显示环形进度条、成功/失败角标、失败可重选。sendChat 参数从 File 改为服务端路径。同时修复 file input 多次上传不重置的问题。
|
||||
|
||||
### [CL-20260412-2315] 2026-04-12 — 修复 Cloudflare Tunnel 跨域开发警告
|
||||
- **tags**: 前端, 配置, Next.js, Cloudflare, 跨域
|
||||
- **affected_files**: art-agent/frontend/next.config.ts
|
||||
- **summary**: Next.js 检测到来自 trycloudflare.com 的跨域请求发出警告。在 next.config.ts 中添加 `allowedDevOrigins: ["*.trycloudflare.com"]` 消除警告,通配符覆盖所有 Quick Tunnel 随机域名。
|
||||
|
||||
### [CL-20260412-2300] 2026-04-12 — 集成 Kolors IP-Adapter,参考图可直接用于风格生成
|
||||
- **tags**: 后端, 前端, IP-Adapter, 风格迁移, 参考图, 模型注册, Replicate, 架构
|
||||
- **affected_files**: art-agent/backend/app/config.py, art-agent/backend/app/services/image_gen.py, art-agent/backend/app/agent/loop.py, art-agent/frontend/src/lib/types.ts, art-agent/frontend/src/components/chat/model-selector.tsx
|
||||
- **summary**: 集成 Kolors IP-Adapter 模型(fofr/kolors-with-ipadapter,~$0.004/次),参考图通过 base64 data URI 直接传给 Replicate 的 IP-Adapter 参与风格生成。模型注册表新增 supports_ref_image / ref_image_param 通用字段,新增 IP-Adapter 模型只需加配置。to_data_uri 抽为公共函数供 loop.py 和 image_gen.py 共用。前端模型列表显示绿色"参考图"徽章。
|
||||
|
||||
### [CL-20260412-2230] 2026-04-12 — 用户消息气泡中显示参考图缩略图
|
||||
- **tags**: 前端, 参考图, UX, chat-messages
|
||||
- **affected_files**: art-agent/frontend/src/lib/types.ts, art-agent/frontend/src/app/page.tsx, art-agent/frontend/src/components/chat/chat-messages.tsx
|
||||
- **summary**: 用户上传参考图后发送消息,之前聊天气泡中不显示参考图,无法确认是否成功附带。修复:ChatMessage 类型新增 refImageUrl 字段,page.tsx 构造用户消息时用 URL.createObjectURL 保存预览 URL,chat-messages.tsx 在用户消息气泡中渲染缩略图(最大 160×120px)。Blob URL 仅当前会话有效,不持久化。
|
||||
|
||||
### [CL-20260412-2200] 2026-04-12 — 修复 DeepSeek 不支持 image_url 导致参考图上传报错
|
||||
- **tags**: bug修复, 后端, Agent Loop, vision, DeepSeek, 多模态
|
||||
- **affected_files**: art-agent/backend/app/agent/loop.py
|
||||
- **summary**: 上传参考图时使用 OpenAI Vision 格式(`image_url` content type)发送给 DeepSeek API,但 DeepSeek 只支持 `text` 类型,导致 400 错误。修复:新增 vision 能力检测(基于模型名称关键词),不支持 vision 的模型改为文字提示方式告知 LLM 有参考图,参考图仍传给图像生成工具处理。
|
||||
|
||||
### [CL-20260412-2130] 2026-04-12 — 修复图片生成失败时前端显示破碎图标
|
||||
- **tags**: bug修复, 前端, 后端, 图像生成, 错误处理
|
||||
- **affected_files**: art-agent/backend/app/agent/tools.py, art-agent/frontend/src/app/page.tsx
|
||||
- **summary**: Replicate API 调用失败(如余额不足 402)时,错误字符串 `[生成失败: ...]` 被混入 images 列表传给前端,导致 `<img>` 标签渲染破碎图标。修复:后端 tools.py 分离有效 URL 和错误信息为 images/errors 两个字段;前端 page.tsx 过滤掉以 `[` 开头的无效 URL,无有效图片时不渲染图片网格。
|
||||
|
||||
### [CL-20260412-2100] 2026-04-12 — 生图模型动态切换:Provider 抽象 + 前端模型选择器
|
||||
- **tags**: 后端, 前端, 图像生成, 模型切换, Provider, 重构, Replicate
|
||||
- **affected_files**: art-agent/backend/app/config.py, art-agent/backend/app/services/image_gen.py, art-agent/backend/app/api/chat.py, art-agent/backend/app/agent/loop.py, art-agent/backend/app/agent/tools.py, art-agent/backend/.env, art-agent/backend/.env.example, art-agent/frontend/src/lib/types.ts, art-agent/frontend/src/lib/api.ts, art-agent/frontend/src/components/chat/model-selector.tsx, art-agent/frontend/src/components/chat/chat-input.tsx, art-agent/frontend/src/app/page.tsx
|
||||
- **summary**: 将图像生成从 Replicate 硬绑定重构为 Provider 抽象层。后端:config.py 新增 IMAGE_MODELS 注册表(flux-schnell / flux-dev / SDXL),image_gen.py 引入 ImageProvider 基类 + ReplicateProvider 实现,chat.py 新增 GET /api/models + POST /api/chat 增加 image_model 参数,agent loop / tools 全链路透传。前端:新建 ModelSelector 下拉组件集成到 ChatInput,每条消息可选不同模型,选择持久化到 localStorage。
|
||||
|
||||
### [CL-20260412-1800] 2026-04-12 — 移动端适配 + Cloudflare Tunnel 内网穿透
|
||||
- **tags**: 前端, 响应式, 移动端, 部署, Cloudflare, 穿透, 配置
|
||||
- **affected_files**: art-agent/frontend/src/app/layout.tsx, art-agent/frontend/src/app/globals.css, art-agent/frontend/src/app/page.tsx, art-agent/frontend/src/app/gallery/page.tsx, 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, 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/lib/app-context.tsx, art-agent/frontend/next.config.ts, art-agent/start-tunnel.ps1, art-agent/README.md
|
||||
- **summary**: 为实现"手机浏览器远程访问"做了两大块工作。(1) 移动端响应式适配:侧边栏改为固定定位抽屉式(md 以下),顶栏新增汉堡菜单,图片详情面板移动端全屏 overlay,气泡/输入框/Gallery 网格间距微调,hover 操作在移动端始终可见,默认小屏折叠侧边栏。(2) 穿透方案:安装 cloudflared,编写 start-tunnel.ps1 一键脚本自动创建双隧道 + 更新 .env.local + 退出时恢复。Next.js 图片白名单加 trycloudflare.com。uvicorn 改绑 0.0.0.0。路线 B(云服务器部署)记为延期方案。
|
||||
|
||||
### [CL-20260412-1530] 2026-04-12 — 修复 .env 配置加载时序问题
|
||||
- **tags**: 后端, bug修复, 配置, dotenv, Python
|
||||
- **affected_files**: art-agent/backend/app/main.py, 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
|
||||
- **summary**: 切换 DeepSeek 后报 "Model Not Exist"。根因:(1) load_dotenv() 在业务模块 import 之后执行,config.py 的模块级变量在 import 时就固化为默认值 gpt-4o-mini;(2) load_dotenv 默认 override=False 不覆盖已有环境变量。修复:load_dotenv(override=True) 提到所有 import 之前;config.py 常量改为函数式懒读取;.env base_url 改为不带 /v1。
|
||||
|
||||
### [CL-20260412-1500] 2026-04-12 — 品牌重命名 EPEEKit + API 配置集中化
|
||||
- **tags**: EPEEKit, 品牌, 配置, 后端, 前端, 重构
|
||||
- **affected_files**: art-agent/frontend/src/app/layout.tsx, art-agent/frontend/src/components/layout/top-nav.tsx, art-agent/frontend/src/app/page.tsx, art-agent/frontend/src/lib/store.ts, 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/backend/app/main.py, 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, art-agent/backend/.env.example, art-agent/README.md
|
||||
- **summary**: 应用正式命名为 "EPEEKit",全部用户可见文案 + 文件名前缀 + localStorage 键名统一替换。后端新增 config.py 集中管理 LLM_MODEL、IMAGE_MODEL 等原硬编码配置,.env 重组为带注释的分组结构,切换 LLM 只需改 3 个环境变量。同时新增 .env.example 模板和 Logo SVG。
|
||||
|
||||
### [CL-20260411-1500] 2026-04-11 — 完成美术 Agent 产品决策和技术选型
|
||||
- **tags**: art-agent, 产品决策, 技术选型, 规划
|
||||
- **affected_files**: docs/art-agent/DECISIONS.md, docs/art-agent/TECH-STACK.md
|
||||
- **summary**: 5 轮结构化讨论确定产品决策(Chat-first Web App、对话驱动交互、三层风格定义等)。8 维度技术选型:Next.js / FastAPI / 自建 Agent Loop / PostgreSQL / Replicate / Vercel+Railway。DECISIONS.md 和 TECH-STACK.md 两份文档产出。
|
||||
|
||||
@@ -2,7 +2,94 @@
|
||||
|
||||
## Active Items
|
||||
|
||||
(暂无延期方案)
|
||||
### [cloud-deploy-route-b] 路线 B:云服务器正式部署
|
||||
- **status**: deferred
|
||||
- **tags**: deployment, docker, nginx, cloud, production
|
||||
- **recorded**: 2026-04-12
|
||||
- **source_chat**: [发布到手机浏览器的方案讨论](discussion-publish-routes)
|
||||
- **prerequisite**: 路线 A(内网穿透 + 移动端适配)完成后
|
||||
- **related_files**:
|
||||
- art-agent/backend/app/main.py
|
||||
- art-agent/frontend/next.config.ts
|
||||
- art-agent/frontend/.env.local
|
||||
- art-agent/backend/.env
|
||||
- **context**: |
|
||||
买轻量云服务器(2C2G ~50元/月),编写前后端 Dockerfile + docker-compose,
|
||||
配置 Nginx/Caddy 反向代理统一入口,HTTPS 自动签证书,
|
||||
环境变量搬迁(去掉本地代理配置),可选绑定域名。
|
||||
预估工作量 1-2 天。
|
||||
- **chosen_alternative**: 路线 A — 本地运行 + 内网穿透(Cloudflare Tunnel / ngrok)
|
||||
- **deferred_reason**: 当前阶段只需自己和朋友试用,内网穿透足够
|
||||
|
||||
### [style-pipeline-layered] 分层组合风格一致性产线
|
||||
- **status**: deferred
|
||||
- **tags**: 风格一致性, IP-Adapter, LoRA, ControlNet, 量产, 美术产线, InstantStyle
|
||||
- **recorded**: 2026-04-12
|
||||
- **updated**: 2026-04-13
|
||||
- **source_chat**: [风格一致性技术方案讨论](style-consistency-discussion)
|
||||
- **prerequisite**: EPEEKit 进入美术资源量产阶段(风格方向已确定、需要批量产出同风格素材)
|
||||
- **related_files**:
|
||||
- art-agent/backend/app/services/image_gen.py
|
||||
- art-agent/backend/app/config.py
|
||||
- **context**: |
|
||||
分层组合的风格一致性产线:
|
||||
1. 探索期(当前):Prompt + 参考图,快速试错确定风格方向
|
||||
2. 锁定期:IP-Adapter / ControlNet,选 3-5 张精选图作为风格锚点,推理时注入风格
|
||||
3. 量产期:LoRA + ControlNet,用精选图训练 LoRA(20-50 张),批量产出同风格资源
|
||||
4. 贯穿全程:标准化 Prompt 模板 + Negative Prompt 模板,确保品质下限
|
||||
各阶段可叠加使用,不互斥。LoRA 训练需要同风格样本积累到足够数量。
|
||||
|
||||
2026-04-13 调研补充 — 风格迁移模型层级:
|
||||
- Kolors IP-Adapter(当前在用):通用 IP-Adapter,风格迁移弱,内容+风格+构图混合提取
|
||||
- InstantStyle(Replicate 可用):专门分离内容/风格,风格迁移强,但贵且慢
|
||||
- Style IPAdapter for NoobAI-XL(CivitAI):最强画风迁移(线条+着色技法),需 ComfyUI
|
||||
- ICAS 框架(学术前沿 2025.04):IP-Adapter + ControlNet 组合,多主体风格一致性最优
|
||||
锁定期的最佳方案:迁移到 HF Inference Endpoints 后,用 NoobAI-XL + Style IPAdapter + ControlNet
|
||||
- **chosen_alternative**: 当前使用 Prompt Engineering + LLM 参考图理解(探索期方案)
|
||||
- **deferred_reason**: 风格方向尚未确定,过早引入 LoRA/ControlNet 是过度优化
|
||||
|
||||
### [hf-inference-endpoints] 迁移到 Hugging Face + Inference Endpoints
|
||||
- **status**: deferred
|
||||
- **tags**: 基础设施, Hugging Face, Inference Endpoints, ComfyUI, 自定义模型, 风格迁移
|
||||
- **recorded**: 2026-04-13
|
||||
- **source_chat**: [Kolors 风格迁移排查与模型调研](kolors-style-investigation)
|
||||
- **prerequisite**: 探索期结束、确定要用的模型组合后
|
||||
- **related_files**:
|
||||
- art-agent/backend/app/services/image_gen.py
|
||||
- art-agent/backend/app/config.py
|
||||
- **context**: |
|
||||
将生图基础设施从 Replicate API 迁移到 Hugging Face Inference Endpoints:
|
||||
1. 可部署任意 ComfyUI 工作流(NoobAI-XL + Style IPAdapter + ControlNet 等任意组合)
|
||||
2. 不受 Replicate 模型作者暴露的参数限制,完全控制推理流程
|
||||
3. CivitAI 上的任何 LoRA、IP-Adapter 权重都能直接加载
|
||||
4. 按 GPU 时长计费,批量生成时远比 Replicate 按次付费便宜
|
||||
5. 是 style-pipeline-layered 延期方案中"锁定期 → 量产期"的基础设施
|
||||
背景:当前在 Replicate 上可用的风格迁移模型有限——
|
||||
- Kolors IP-Adapter:风格迁移弱(混合提取内容+风格+构图)
|
||||
- InstantStyle(jyoung105/instant-style):风格迁移强但贵($0.12/次)且慢(~128s)
|
||||
- Style IPAdapter for NoobAI-XL:最强画风迁移,但需 ComfyUI 环境,Replicate 上无法使用
|
||||
迁移到 HF Inference Endpoints 后可自由组合以上所有方案。
|
||||
- **chosen_alternative**: 当前使用 Replicate API(Kolors IP-Adapter + Flux + SDXL)
|
||||
- **deferred_reason**: 探索期用 Replicate 足够快速迭代,迁移工作量较大(需搭建自定义推理服务)
|
||||
|
||||
### [vision-model-asset-library] 专用 Vision 模型用于资源库功能
|
||||
- **status**: deferred
|
||||
- **tags**: 资源库, vision, CLIP, BLIP, 图片搜索, 自动标签, embedding
|
||||
- **recorded**: 2026-04-12
|
||||
- **source_chat**: [参考图风格解析方案讨论](vision-model-discussion)
|
||||
- **prerequisite**: 资源库功能进入增强阶段(基础 Gallery 已完成)
|
||||
- **related_files**:
|
||||
- art-agent/frontend/src/app/gallery/page.tsx
|
||||
- art-agent/backend/app/services/image_gen.py
|
||||
- **context**: |
|
||||
引入专用 Vision 模型(CLIP / BLIP 等)为资源库提供智能化能力:
|
||||
1. 自动标签:生成的图片自动分类(UI/角色/场景/图标等)
|
||||
2. 以图搜图:上传一张图,从资源库中找风格最相似的
|
||||
3. 语义搜索:用自然语言搜索图片(如"蓝色水晶质感的按钮")
|
||||
4. 聚类分组:自动将图片按视觉相似性分组
|
||||
可通过 Replicate 调用或本地部署,成本极低。
|
||||
- **chosen_alternative**: 当前资源库使用手动标签 + Prompt 文本搜索
|
||||
- **deferred_reason**: 当前阶段资源量少,手动管理足够;等资源积累到一定量级后再引入自动化
|
||||
|
||||
---
|
||||
|
||||
|
||||
23
.cursor/hooks.json
Normal file
23
.cursor/hooks.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"version": 1,
|
||||
"hooks": {
|
||||
"sessionStart": [
|
||||
{
|
||||
"command": "powershell -ExecutionPolicy Bypass -File .cursor/hooks/session-init.ps1",
|
||||
"timeout": 5
|
||||
}
|
||||
],
|
||||
"stop": [
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "You are a changelog compliance checker. Return ONLY valid JSON, nothing else.\n\nSTEP 1 — EXEMPTION CHECK (if ANY condition is true, return {} immediately):\n- The conversation is in Debug mode, debug-mode, or any debugging/troubleshooting context\n- The agent's recent actions were ONLY: reading files, running shell commands, adding log/debug statements, or modifying .cursor/ files\n- The agent did NOT use Write or StrReplace tools on files outside .cursor/ directory\n- The agent was acknowledging a previous hook reminder\n- There is a CURSOR_SKIP_CHANGELOG environment variable set\n\nIf ANY exemption matches → return: {}\n\nSTEP 2 — Only if NO exemption matched:\nCheck if the agent used Write or StrReplace on source files (*.py, *.tsx, *.ts, *.css, *.json outside .cursor/) AND did NOT also write to all three: .cursor/changelog/changelog-full.md, changelog-recent.md, changelog-headlines.md.\n\nIf changelog writes were missed → return: {\"followup_message\":\"Changelog not synced. Run dev-changelog Skill operation A to write all three changelog layers.\"}\n\nOtherwise → return: {}\n\nHere is the hook input: $ARGUMENTS",
|
||||
"timeout": 15,
|
||||
"loop_limit": 1
|
||||
},
|
||||
{
|
||||
"command": "powershell -ExecutionPolicy Bypass -File .cursor/hooks/check-changelog.ps1",
|
||||
"timeout": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
72
.cursor/hooks/check-changelog.ps1
Normal file
72
.cursor/hooks/check-changelog.ps1
Normal file
@@ -0,0 +1,72 @@
|
||||
# Changelog sync guard: compare source file mtime vs changelog mtime.
|
||||
# If source files are newer than changelog, inject a followup_message
|
||||
# reminding the agent to write changelog entries.
|
||||
#
|
||||
# 静默条件(不触发提醒):
|
||||
# 1. 环境变量 CURSOR_SKIP_CHANGELOG 被设置(由 sessionStart hook 在非 agent 模式设置)
|
||||
# 2. Debug 模式 — 项目根目录存在 debug-*.log 文件,说明正在调试
|
||||
# 3. changelog 文件不存在
|
||||
# 4. .changelog-ack 标记文件存在且足够新(本会话已确认过 changelog 状态)
|
||||
|
||||
$input = [Console]::In.ReadToEnd()
|
||||
|
||||
# 检测 sessionStart 设置的跳过标志(覆盖一开始就是 debug/ask 模式的场景)
|
||||
if ($env:CURSOR_SKIP_CHANGELOG) {
|
||||
Write-Output '{}'
|
||||
exit 0
|
||||
}
|
||||
|
||||
$changelog = ".cursor\changelog\changelog-headlines.md"
|
||||
$srcDir = "art-agent"
|
||||
|
||||
if (-not (Test-Path $changelog)) {
|
||||
Write-Output '{}'
|
||||
exit 0
|
||||
}
|
||||
|
||||
# 检测 debug 模式:项目中存在活跃的 debug 日志文件
|
||||
$debugLogs = Get-ChildItem -Path "." -Filter "debug-*.log" -Recurse -Depth 3 -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.FullName -notlike "*node_modules*" -and $_.FullName -notlike "*venv*" }
|
||||
if ($debugLogs) {
|
||||
Write-Output '{}'
|
||||
exit 0
|
||||
}
|
||||
|
||||
$clMtime = (Get-Item $changelog).LastWriteTime
|
||||
|
||||
# 检测 ack 标记文件:Agent 已确认 changelog 状态(写入或跳过),本会话不再提醒
|
||||
$ackFile = ".cursor\changelog\.changelog-ack"
|
||||
if ((Test-Path $ackFile) -and (Get-Item $ackFile).LastWriteTime -ge $clMtime) {
|
||||
Write-Output '{}'
|
||||
exit 0
|
||||
}
|
||||
|
||||
$extensions = @("*.py", "*.tsx", "*.ts", "*.css")
|
||||
$excludeDirs = @("node_modules", ".next", "__pycache__", "venv")
|
||||
|
||||
$newerFile = $null
|
||||
foreach ($ext in $extensions) {
|
||||
$files = Get-ChildItem -Path $srcDir -Filter $ext -Recurse -ErrorAction SilentlyContinue |
|
||||
Where-Object {
|
||||
$skip = $false
|
||||
foreach ($ex in $excludeDirs) {
|
||||
if ($_.FullName -like "*\$ex\*") { $skip = $true; break }
|
||||
}
|
||||
-not $skip -and $_.LastWriteTime -gt $clMtime
|
||||
} |
|
||||
Select-Object -First 1
|
||||
|
||||
if ($files) {
|
||||
$newerFile = $files.Name
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ($newerFile) {
|
||||
$msg = "[Hook] Source file updated (e.g. $newerFile) but changelog not synced. Run dev-changelog Skill operation A NOW to write all three changelog layers."
|
||||
$json = '{"followup_message":"' + $msg.Replace('"','\"') + '"}'
|
||||
Write-Output $json
|
||||
} else {
|
||||
Write-Output '{}'
|
||||
}
|
||||
exit 0
|
||||
23
.cursor/hooks/session-init.ps1
Normal file
23
.cursor/hooks/session-init.ps1
Normal file
@@ -0,0 +1,23 @@
|
||||
# session-init.ps1 — 会话启动时检测 composer_mode,非 agent 模式设置跳过标志
|
||||
#
|
||||
# sessionStart input 包含 composer_mode 字段("agent" / "ask" / "edit" / "debug" 等)
|
||||
# 通过 env 输出的环境变量会传递给同会话内所有后续 hook
|
||||
|
||||
$input = [Console]::In.ReadToEnd()
|
||||
|
||||
try {
|
||||
$data = $input | ConvertFrom-Json
|
||||
$mode = $data.composer_mode
|
||||
} catch {
|
||||
$mode = $null
|
||||
}
|
||||
|
||||
Remove-Item ".cursor\changelog\.changelog-ack" -ErrorAction SilentlyContinue
|
||||
|
||||
if ($mode -and $mode -ne "agent") {
|
||||
$json = '{"env":{"CURSOR_SKIP_CHANGELOG":"1","CURSOR_COMPOSER_MODE":"' + $mode + '"}}'
|
||||
Write-Output $json
|
||||
} else {
|
||||
Write-Output '{}'
|
||||
}
|
||||
exit 0
|
||||
13
.cursor/pitfalls/pitfalls.md
Normal file
13
.cursor/pitfalls/pitfalls.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Pitfall Journal
|
||||
|
||||
开发过程中踩过的坑,按时间倒序排列。
|
||||
Agent 进入 Debug mode 或遇到运行时错误时自动检索匹配。
|
||||
|
||||
---
|
||||
|
||||
### [PF-20260412-1530] Python load_dotenv 默认不覆盖已有环境变量 + 模块级变量在 import 时固化
|
||||
- **症状**: 修改 .env 切换 API 供应商后,后端仍报旧供应商的错误(如 DeepSeek 报 "Model Not Exist",实际发送的模型名是 OpenAI 的 gpt-4o-mini)
|
||||
- **根因**: 两层叠加:(1) `load_dotenv()` 默认 `override=False`,如果进程/系统中已有同名环境变量,.env 中的新值不会生效;(2) `config.py` 使用模块级常量 `LLM_MODEL = os.getenv(...)` 在 import 时就求值固化,而 `main.py` 的 import 链在 `load_dotenv()` 之前就触发了 config.py 的加载
|
||||
- **解法**: (1) `load_dotenv(override=True)` 并提到所有业务 import 之前;(2) config.py 改为函数式 `get_llm_model()`,运行时才读取
|
||||
- **防御**: 任何 Python 项目使用 dotenv 时,始终 `override=True` + 放在文件最顶部(仅在 `import os` 和 `from dotenv import load_dotenv` 之后);配置值用函数或属性包装,不要用模块级常量
|
||||
- **关联**: Python, dotenv, FastAPI, uvicorn, 环境变量, 配置管理, OpenAI SDK
|
||||
@@ -12,6 +12,32 @@ alwaysApply: true
|
||||
3. 这些信息帮助 Agent 快速建立位置感:项目进展到什么阶段、最近的工作重心在哪个模块
|
||||
4. 在后续回复中自然参考,不显式提及"根据开发日志"
|
||||
|
||||
## 主动定位辅助
|
||||
|
||||
L3 概要的核心价值之一是帮助 Agent 在**冷启动**(新会话、无上下文)时理解用户意图。
|
||||
当用户的请求缺少具体文件名或模块名时,Agent 应主动利用 L3 进行推断:
|
||||
|
||||
### 典型场景
|
||||
|
||||
1. **隐式延续**:用户说"继续做昨天那个"、"把那个功能完善一下"
|
||||
→ 从 L3 中找到最近的相关条目,上溯到 L2 获取具体文件列表
|
||||
2. **模糊指代**:用户说"那个组件有 bug"、"之前改的那个接口"
|
||||
→ 用 L3 中的关键词匹配用户描述,定位到具体改动
|
||||
3. **上下文补全**:用户直接提出一个任务,没有背景说明
|
||||
→ 用 L3 判断该任务是否与近期某个改动有关联(如同一模块、同一功能线)
|
||||
|
||||
### 流程
|
||||
|
||||
```
|
||||
1. 解析用户请求,识别是否存在隐式引用或模糊指代
|
||||
2. 在 L3 概要中查找语义最匹配的 1-3 条记录
|
||||
3. 提取匹配条目的锚点 ID,上溯到 L2 获取 affected_files 和 tags
|
||||
4. 如有必要,继续上溯到 L1 获取完整的决策背景
|
||||
5. 将定位到的文件/模块作为任务的起点,开始执行
|
||||
```
|
||||
|
||||
如果 L3 中没有匹配到任何相关记录,正常处理即可——不是所有任务都与近期改动有关。
|
||||
|
||||
## L2 自动触发
|
||||
|
||||
Agent 开始处理一个新任务时,判断是否需要读取近期详细记录:
|
||||
@@ -42,7 +68,30 @@ Agent 开始处理一个新任务时,判断是否需要读取近期详细记
|
||||
获取行号后用 Read 工具读取该行号 ±20 行范围
|
||||
4. 一次上溯通常只涉及 1-3 条记录,不批量上溯
|
||||
|
||||
## 被动写入提醒
|
||||
## 任务完成 Checklist(强制)
|
||||
|
||||
Agent 在完成涉及代码/配置文件实质性改动的任务后,应读取 `dev-changelog` Skill
|
||||
并执行其"操作 A:记录写入"流程,静默追加三层记录。
|
||||
Agent 在即将输出最终回复前,**必须**逐项检查以下清单。
|
||||
这是硬性要求,不是建议——**跳过任何一项都视为执行错误**。
|
||||
|
||||
1. **本次是否有代码/配置文件改动?**(不含 `.cursor/` 下的基础设施文件)
|
||||
- 否 → 跳过后续项
|
||||
- 是 → 继续
|
||||
|
||||
2. **是否已写入三层开发日志?**
|
||||
- 否 → **立即**读取 `dev-changelog` Skill 并执行操作 A,写入 L1 + L2 + L3 后再输出回复
|
||||
- 是 → 继续
|
||||
|
||||
3. **是否修改了任何 Skill?**(包括 SKILL.md 内容变更)
|
||||
- 否 → 跳过
|
||||
- 是 → 检查是否已同步 `epee-orchestrator` 的 `registry.md`,未同步则立即执行
|
||||
|
||||
4. **本次是否有 Skill 使用异常?**(遗漏、误触、产物与用户预期偏差)
|
||||
- 否 → 跳过
|
||||
- 是 → 执行 `epee-orchestrator.mdc` 中的自迭代确认流程
|
||||
|
||||
5. **静默 Hook 重复触发**(每次 checklist 完成后必须执行)
|
||||
- 用 Write 工具创建空文件 `.cursor/changelog/.changelog-ack`
|
||||
- 这会更新 ack 文件的 mtime,阻止 `check-changelog.ps1` hook 在后续回复中重复提醒
|
||||
|
||||
**执行原则**:先完成 checklist 中的所有写入动作,再输出面向用户的回复文本。
|
||||
回复末尾如果执行了第 2 项,附 `[已记录到开发日志]`。
|
||||
|
||||
@@ -28,6 +28,9 @@ Agent **必须**执行以下操作:
|
||||
2. 更新或新增对应 Skill 的条目(格式参见 registry.md 中的条目结构)
|
||||
3. 确保条目中的能力描述和触发场景与 Skill 实际内容一致
|
||||
|
||||
> **注意**:此项已纳入 `changelog-recall.mdc` 的"任务完成 Checklist"第 3 项。
|
||||
> 如果 Agent 在 checklist 阶段发现遗漏,必须立即补执行。
|
||||
|
||||
### Skill 自迭代(强制)
|
||||
|
||||
每个 SKILL.md 必须包含一个"自迭代日志"章节,用于记录使用该 Skill 过程中发现的经验教训。
|
||||
@@ -38,6 +41,9 @@ Agent **必须**执行以下操作:
|
||||
2. 用户需要反复补充同类信息
|
||||
3. 生成产物与用户预期存在系统性偏差
|
||||
|
||||
> **注意**:此项已纳入 `changelog-recall.mdc` 的"任务完成 Checklist"第 4 项。
|
||||
> Agent 不应等到"下次使用 Skill 时"才想起自迭代——当次就应检查。
|
||||
|
||||
**流程**:
|
||||
|
||||
1. 识别问题根因,归纳为一条简明的检查项
|
||||
|
||||
31
.cursor/rules/common/pitfall-recall.mdc
Normal file
31
.cursor/rules/common/pitfall-recall.mdc
Normal file
@@ -0,0 +1,31 @@
|
||||
## 踩坑经验自动检索
|
||||
|
||||
### 被动检测触发
|
||||
|
||||
Agent 在以下场景中,应自动读取 `.cursor/pitfalls/pitfalls.md` 并进行匹配检索:
|
||||
|
||||
1. **进入 Debug mode**:读取全部条目,将当前错误症状与已有记录比对
|
||||
2. **遇到运行时错误**:提取错误信息关键词,在"症状"字段中检索匹配
|
||||
3. **同一问题第二次出现**:如果当前会话中某个错误已出现过一次且未解决,强制检索
|
||||
|
||||
### 匹配策略
|
||||
|
||||
```
|
||||
1. 提取当前问题的信号:错误信息关键词、涉及文件/模块、技术栈
|
||||
2. 在 pitfalls.md 中匹配:
|
||||
- 硬匹配:错误关键词出现在条目的"症状"中
|
||||
- 软匹配:模块/技术栈出现在条目的"关联"中
|
||||
3. 命中时在分析开头提示:
|
||||
> 注意:之前遇到过类似问题 [PF-xxx]:[标题]。根因是 [xxx],先排查这个方向。
|
||||
```
|
||||
|
||||
### 写入提醒
|
||||
|
||||
Agent 在完成涉及 debug/修复的任务后,应读取 `pitfall-journal` Skill 并执行其"操作 A:写入记录"流程。
|
||||
判断标准:问题的根因是否"非显而易见"——如果只看代码逻辑觉得应该没问题,但实际运行时才暴露,就值得记录。
|
||||
|
||||
### 注意
|
||||
|
||||
- 检索结果是**辅助参考**,不是确定性答案——匹配到不代表根因一定相同
|
||||
- pitfalls.md 不存在时跳过,不报错
|
||||
- 每次会话中对同一条 pitfall 最多提醒一次
|
||||
18
.cursor/rules/project/project-launcher.mdc
Normal file
18
.cursor/rules/project/project-launcher.mdc
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
description: 当用户要求启动项目、运行项目、打开前端/后端服务时触发
|
||||
globs:
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
## 项目启动快捷指令
|
||||
|
||||
当用户表达以下意图时,读取并执行 `project-launcher` Skill:
|
||||
|
||||
**触发关键词**:启动项目、运行项目、跑起来、打开前端和后端、启动服务、start、launch、run dev、启动前端、启动后端
|
||||
|
||||
**执行方式**:
|
||||
|
||||
1. 读取 `.cursor/skills/project-launcher/SKILL.md`
|
||||
2. 按 Skill 中的流程,在**独立可见的终端窗口**中启动前端和/或后端
|
||||
3. 必须使用 `Start-Process`(PowerShell)或 `start cmd`(CMD)打开新窗口
|
||||
4. **不要**在 Cursor 内置终端中后台运行——用户需要看到窗口并能手动关闭
|
||||
@@ -15,7 +15,7 @@ description: >-
|
||||
| 层级 | 文件 | 信息密度 | 条目数量 | 注入方式 |
|
||||
|------|------|---------|---------|---------|
|
||||
| L1 完整版 | `changelog-full.md` | 高(5-15 行/条) | 无上限,只追加 | 用户手动唤醒 |
|
||||
| L2 中期版 | `changelog-recent.md` | 中(3-5 行/条) | 滚动窗口 ~10 条 | 检测到关联时自动读取 |
|
||||
| L2 中期版 | `changelog-recent.md` | 中(3-5 行/条) | 滚动窗口 ~20 条 | 检测到关联时自动读取 |
|
||||
| L3 概要版 | `changelog-headlines.md` | 低(1 行/条) | 滚动窗口 ~50 条 | 每次会话自动注入 |
|
||||
|
||||
所有数据文件存放在 `.cursor/changelog/` 目录下。
|
||||
@@ -182,12 +182,12 @@ Agent 完成了一个涉及**代码或配置文件实质性改动**的任务后
|
||||
|
||||
## 滚动窗口维护
|
||||
|
||||
### L2 窗口(~10 条)
|
||||
### L2 窗口(~20 条)
|
||||
|
||||
```
|
||||
写入新条目后,检查总条目数:
|
||||
- <= 10 条:不做处理
|
||||
- > 10 条:移除文件底部(最旧的)条目,直到恰好 10 条
|
||||
- <= 20 条:不做处理
|
||||
- > 20 条:移除文件底部(最旧的)条目,直到恰好 20 条
|
||||
```
|
||||
|
||||
### L3 窗口(~50 条)
|
||||
@@ -246,4 +246,4 @@ Agent 完成了一个涉及**代码或配置文件实质性改动**的任务后
|
||||
|
||||
### 已知必要检查
|
||||
|
||||
(暂无)
|
||||
1. **大任务收尾遗漏风险** — 当单次任务涉及 5+ 个文件改动时,Agent 容易在输出总结回复后遗漏被动写入流程。应在生成最终回复前,先执行 `changelog-recall.mdc` 中的"任务完成 Checklist",确认三层日志已写入后再输出回复。绝不能"先回复再补写"。
|
||||
|
||||
@@ -122,4 +122,4 @@ description: >-
|
||||
|
||||
### 已知必要检查
|
||||
|
||||
(暂无)
|
||||
1. **收尾动作级联遗漏** — 当 Agent 遗漏了一个收尾动作(如 changelog 写入)后,后续的收尾动作(自迭代、Registry 同步)也会被一并遗漏,因为它们都在同一个"收尾阶段"。`changelog-recall.mdc` 中的 Checklist 化设计可以打断这种级联——每项独立检查,不依赖前一项的执行记忆。
|
||||
|
||||
@@ -39,4 +39,20 @@
|
||||
- **触发场景**: "开发日志"、"changelog"、"最近改了什么"、"回顾改动"、"查看开发记录"、代码改动后自动写入
|
||||
- **输出**: .cursor/changelog/ 下的 changelog-full.md、changelog-recent.md、changelog-headlines.md
|
||||
- **路径**: .cursor/skills/dev-changelog/SKILL.md
|
||||
- **备注**: 写入由 changelog-recall Rule 的被动写入提醒触发;L3 概要每次会话自动注入上下文
|
||||
- **备注**: 写入由 changelog-recall Rule 的"任务完成 Checklist"触发(原被动写入提醒已升级为强制 checklist);L3 概要每次会话自动注入上下文;stop Hook 双保险兜底
|
||||
|
||||
### pitfall-journal
|
||||
- **类型**: 基础设施
|
||||
- **能力**: 记录开发中踩过的坑(非显而易见的问题),在遇到同类问题时自动检索匹配已有经验
|
||||
- **触发场景**: debug 完成后、"踩坑"、"之前遇到过"、"坑"、进入 Debug mode、同类错误反复出现
|
||||
- **输出**: .cursor/pitfalls/pitfalls.md 条目
|
||||
- **路径**: .cursor/skills/pitfall-journal/SKILL.md
|
||||
- **备注**: 与 dev-changelog 互补——changelog 记事实,pitfall 记经验;由 pitfall-recall Rule 触发自动检索
|
||||
|
||||
### project-launcher
|
||||
- **类型**: 项目级
|
||||
- **能力**: 一键在独立可见终端窗口中启动 Art Agent 前端和后端服务
|
||||
- **触发场景**: "启动项目"、"运行项目"、"跑起来"、"打开前端和后端"、"启动服务"、"start"、"launch"、"run dev"、"启动前端"、"启动后端"
|
||||
- **输出**: 两个独立的终端窗口(前端 Next.js + 后端 FastAPI)
|
||||
- **路径**: .cursor/skills/project-launcher/SKILL.md
|
||||
- **备注**: 项目专属 Skill;窗口必须可见,用户可直接查看日志和手动关闭
|
||||
|
||||
116
.cursor/skills/pitfall-journal/SKILL.md
Normal file
116
.cursor/skills/pitfall-journal/SKILL.md
Normal file
@@ -0,0 +1,116 @@
|
||||
---
|
||||
name: pitfall-journal
|
||||
description: >-
|
||||
踩坑经验记录系统。在调试完成或发现非显而易见的坑后记录根因和解决方式,
|
||||
后续遇到同类问题时自动检索匹配,避免重复踩坑。
|
||||
当 debug 完成、问题反复出现、或用户提到"踩坑"、"之前遇到过"、"坑"时触发。
|
||||
---
|
||||
|
||||
# Pitfall Journal
|
||||
|
||||
记录开发过程中遇到的"坑"——那些不看代码逻辑觉得应该没问题、但实际运行时才暴露的问题。
|
||||
与 dev-changelog 互补:changelog 记"做了什么",pitfall-journal 记"踩了什么坑、怎么爬出来的"。
|
||||
|
||||
## 数据文件
|
||||
|
||||
所有记录存放在 `.cursor/pitfalls/pitfalls.md`。
|
||||
|
||||
## 条目格式
|
||||
|
||||
```markdown
|
||||
### [PF-YYYYMMDD-HHMM] 一句话标题
|
||||
- **症状**: 用户/系统看到的错误表现
|
||||
- **根因**: 技术层面的真正原因
|
||||
- **解法**: 具体怎么修的
|
||||
- **防御**: 以后如何避免(可选,如果有通用性的话)
|
||||
- **关联**: 相关文件、模块、技术栈标签
|
||||
```
|
||||
|
||||
## 操作 A:写入记录
|
||||
|
||||
### 触发条件
|
||||
|
||||
以下任一场景触发:
|
||||
|
||||
1. **调试完成后** — 经历了 debug 过程并找到了非显而易见的根因
|
||||
2. **用户主动提及** — "记录一下这个坑"、"以后别再犯"
|
||||
3. **Agent 识别到经验价值** — 问题涉及框架/库的隐式行为、配置陷阱、环境差异等
|
||||
|
||||
以下情况**不触发**:
|
||||
- 纯拼写错误、简单语法错误
|
||||
- 问题原因一目了然(如变量名打错)
|
||||
- 纯业务逻辑调整(不涉及"坑"的语义)
|
||||
|
||||
### 流程
|
||||
|
||||
```
|
||||
1. 生成条目 ID:PF-YYYYMMDD-HHMM
|
||||
2. 从调试过程中提取:症状、根因、解法
|
||||
3. 归纳防御措施(如果有通用性)
|
||||
4. 读取 pitfalls.md,在顶部追加新条目
|
||||
5. 在回复末尾附:[已记录到踩坑日志]
|
||||
```
|
||||
|
||||
### 静默写入原则
|
||||
|
||||
与 dev-changelog 一致——Agent 自己调试出来的问题,不需要用户确认就可以记录。
|
||||
|
||||
## 操作 B:自动匹配检索
|
||||
|
||||
### 触发条件
|
||||
|
||||
当 Agent 在当前任务中遇到以下情况时,应主动检索 pitfalls.md:
|
||||
|
||||
1. **进入 Debug mode** — 读取 pitfalls.md,扫描是否有与当前错误症状匹配的记录
|
||||
2. **同类错误再现** — 错误信息关键词与已有条目的"症状"匹配
|
||||
3. **涉及已知高危区域** — 当前操作涉及的模块/技术栈在已有条目的"关联"中出现
|
||||
|
||||
### 匹配策略
|
||||
|
||||
```
|
||||
1. 提取当前问题的关键信号:
|
||||
- 错误信息关键词
|
||||
- 涉及的文件/模块
|
||||
- 涉及的技术栈/框架
|
||||
|
||||
2. 在 pitfalls.md 中匹配:
|
||||
- 硬匹配:错误信息关键词出现在条目的"症状"中
|
||||
- 软匹配:涉及的模块/技术栈出现在条目的"关联"中
|
||||
|
||||
3. 命中时,在分析中优先考虑已有经验:
|
||||
> 注意:之前遇到过类似问题 [PF-xxx]:[一句话描述]。
|
||||
> 上次的根因是 [xxx],先排查这个方向。
|
||||
```
|
||||
|
||||
## 操作 C:手动检索
|
||||
|
||||
### 触发条件
|
||||
|
||||
用户主动要求回顾踩坑记录。典型话语:
|
||||
- "之前那个坑是什么来着"
|
||||
- "看看踩坑日志"
|
||||
- "有遇到过类似的问题吗"
|
||||
|
||||
### 流程
|
||||
|
||||
```
|
||||
1. 读取 pitfalls.md
|
||||
2. 根据用户描述匹配相关条目
|
||||
3. 展示匹配结果
|
||||
```
|
||||
|
||||
## 与其他系统的协作
|
||||
|
||||
| 系统 | 关系 | 说明 |
|
||||
|------|------|------|
|
||||
| `dev-changelog` | 互补 | changelog 记改动事实,pitfall 记经验教训 |
|
||||
| `pitfall-recall` Rule | 下游消费者 | 进入 Debug mode 或遇到错误时自动触发检索 |
|
||||
| `epee-orchestrator` | 注册 | 在 registry.md 中注册本 Skill |
|
||||
|
||||
## 自迭代日志
|
||||
|
||||
本节记录使用本 Skill 过程中发现的必要检查项。
|
||||
|
||||
### 已知必要检查
|
||||
|
||||
(暂无)
|
||||
131
.cursor/skills/project-launcher/SKILL.md
Normal file
131
.cursor/skills/project-launcher/SKILL.md
Normal file
@@ -0,0 +1,131 @@
|
||||
---
|
||||
name: project-launcher
|
||||
description: >-
|
||||
Art Agent 项目一键启动。当用户说"启动项目"、"运行项目"、"打开前端和后端"等时触发,
|
||||
自动在独立的可见终端窗口中启动前端(Next.js)和后端(FastAPI),方便用户随时查看和关闭。
|
||||
---
|
||||
|
||||
# Project Launcher
|
||||
|
||||
一键启动 Art Agent 的前端和后端服务,在**独立可见的终端窗口**中运行,
|
||||
用户可以随时查看日志或手动关闭。
|
||||
|
||||
## 触发条件
|
||||
|
||||
当用户表达以下意图时触发:
|
||||
- "启动项目"、"运行项目"、"跑起来"
|
||||
- "打开前端和后端"、"启动服务"
|
||||
- "start"、"launch"、"run dev"
|
||||
- "启动后端"、"启动前端"(可单独启动其中一个)
|
||||
|
||||
## 项目路径
|
||||
|
||||
| 组件 | 路径 | 启动命令 |
|
||||
|------|------|---------|
|
||||
| 后端 | `art-agent/backend` | `uvicorn app.main:app --reload --host 0.0.0.0 --port 8000` |
|
||||
| 前端 | `art-agent/frontend` | `npm run dev` |
|
||||
|
||||
## 前置条件
|
||||
|
||||
后端需要激活 Python 虚拟环境(`art-agent/backend/venv`)。
|
||||
前端需要 Node.js >= 18。
|
||||
|
||||
## 环境 PATH 须知
|
||||
|
||||
本机 Node.js 安装在 `C:\Program Files\nodejs\` 但**未加入系统 PATH**。
|
||||
新开的终端窗口默认找不到 `node` / `npm` 命令。
|
||||
|
||||
**解决方式**:在启动前端的命令中,先将 Node.js 路径注入到当前会话的 `$env:PATH` 中。
|
||||
|
||||
> 如果后续 Node.js 路径发生变化(如用户重新安装或使用 nvm),需要更新此处。
|
||||
|
||||
## 核心操作:启动服务
|
||||
|
||||
### 流程
|
||||
|
||||
```
|
||||
1. 确定项目根目录(workspace 根目录下的 art-agent/)
|
||||
|
||||
2. 确定操作系统和 Shell 类型(Windows / macOS / Linux)
|
||||
|
||||
3. 启动后端(在独立可见终端窗口中):
|
||||
- Windows(PowerShell 或 CMD 均适用):
|
||||
使用 `Start-Process` 或 `start cmd` 打开新的终端窗口
|
||||
- macOS/Linux:
|
||||
使用对应的终端打开方式
|
||||
|
||||
4. 启动前端(在另一个独立可见终端窗口中):
|
||||
- 同样在新的终端窗口中启动
|
||||
|
||||
5. 确认两个服务正在运行,告知用户访问地址
|
||||
```
|
||||
|
||||
### Windows 启动命令
|
||||
|
||||
**关键要求**:必须在**新的、可见的终端窗口**中启动,不能在 Cursor 内置终端后台运行。
|
||||
|
||||
#### PowerShell 环境
|
||||
|
||||
启动后端:
|
||||
```powershell
|
||||
Start-Process powershell -ArgumentList '-NoExit', '-Command', "cd 'BACKEND_PATH'; .\venv\Scripts\Activate.ps1; uvicorn app.main:app --reload --host 0.0.0.0 --port 8000" -WindowStyle Normal
|
||||
```
|
||||
|
||||
启动前端(注意注入 Node.js PATH):
|
||||
```powershell
|
||||
Start-Process powershell -ArgumentList '-NoExit', '-Command', "& { `$env:PATH = 'C:\Program Files\nodejs;' + `$env:PATH; `$Host.UI.RawUI.WindowTitle = 'Art Agent Frontend'; cd 'FRONTEND_PATH'; npm run dev }" -WindowStyle Normal
|
||||
```
|
||||
|
||||
#### CMD 环境
|
||||
|
||||
启动后端:
|
||||
```cmd
|
||||
start "Art Agent Backend" cmd /k "cd /d BACKEND_PATH && venv\Scripts\activate && uvicorn app.main:app --reload --host 0.0.0.0 --port 8000"
|
||||
```
|
||||
|
||||
启动前端(注意注入 Node.js PATH):
|
||||
```cmd
|
||||
start "Art Agent Frontend" cmd /k "set PATH=C:\Program Files\nodejs;%PATH% && cd /d FRONTEND_PATH && npm run dev"
|
||||
```
|
||||
|
||||
### macOS / Linux 启动命令
|
||||
|
||||
根据用户终端环境选择:
|
||||
|
||||
```bash
|
||||
# 后端
|
||||
osascript -e 'tell application "Terminal" to do script "cd BACKEND_PATH && source venv/bin/activate && uvicorn app.main:app --reload --host 0.0.0.0 --port 8000"'
|
||||
|
||||
# 前端
|
||||
osascript -e 'tell application "Terminal" to do script "cd FRONTEND_PATH && npm run dev"'
|
||||
```
|
||||
|
||||
### 执行注意事项
|
||||
|
||||
1. **路径拼接**:`BACKEND_PATH` 和 `FRONTEND_PATH` 必须替换为实际的绝对路径
|
||||
2. **venv 存在性检查**:启动后端前先确认 `art-agent/backend/venv` 目录存在,
|
||||
不存在时提醒用户先创建虚拟环境
|
||||
3. **依赖检查**:如果 `node_modules` 不存在,先提醒用户执行 `npm install`
|
||||
4. **窗口标题**:尽量为窗口设置有意义的标题(如 "Art Agent Backend"、"Art Agent Frontend"),
|
||||
方便用户在任务栏中识别
|
||||
5. **不使用 `block_until_ms: 0`**:不要用 Cursor 的后台命令方式,
|
||||
那样窗口不可见,用户无法直接查看和关闭
|
||||
|
||||
## 单独启动
|
||||
|
||||
如果用户只说"启动前端"或"启动后端",只启动对应的服务即可,不需要全部启动。
|
||||
|
||||
## 访问信息
|
||||
|
||||
启动完成后告知用户:
|
||||
- 后端 API:http://localhost:8000
|
||||
- 后端文档:http://localhost:8000/docs
|
||||
- 前端页面:http://localhost:3000
|
||||
|
||||
## 自迭代日志
|
||||
|
||||
本节记录使用本 Skill 过程中发现的必要检查项。
|
||||
|
||||
### 已知必要检查
|
||||
|
||||
1. **Node.js PATH 注入** — 本机 Node.js (`C:\Program Files\nodejs\`) 未加入系统 PATH,新开的终端窗口默认找不到 `npm`。启动前端时必须先将此路径注入到会话 PATH 中。
|
||||
Reference in New Issue
Block a user