diff --git a/.memory/worklog.json b/.memory/worklog.json index 97fce2e..313152f 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,39 +1,5 @@ { "entries": [ - { - "files_changed": 4, - "hash": "3462758", - "message": "feat: simplify storyboard video card flow", - "ts": "2026-05-19T11:05:57+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "hash": "f4d456c", - "message": "docs: update storyboard card workflow rules", - "ts": "2026-05-19T11:07:30+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "hash": "6d950ef", - "message": "docs: record storyboard card deployment", - "ts": "2026-05-19T11:14:21+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:docs: record storyboard card deployment", - "ts": "2026-05-19T03:14:32Z", - "type": "session-heartbeat" - }, - { - "files_changed": 2, - "hash": "b4d8d81", - "message": "auto-save 2026-05-19 11:18 (~2)", - "ts": "2026-05-19T11:18:36+08:00", - "type": "commit" - }, { "files_changed": 2, "hash": "0d3397c", @@ -3223,6 +3189,37 @@ "message": "auto-save 2026-05-21 15:20 (~2)", "hash": "b6fec10", "files_changed": 2 + }, + { + "ts": "2026-05-21T15:26:00+08:00", + "type": "commit", + "message": "auto-save 2026-05-21 15:25 (~2)", + "hash": "02a9999", + "files_changed": 2 + }, + { + "ts": "2026-05-21T07:28:17Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-21 15:25 (~2)", + "files_changed": 1 + }, + { + "ts": "2026-05-21T07:30:24Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-21 15:25 (~2)", + "files_changed": 1 + }, + { + "ts": "2026-05-21T07:38:17Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-21 15:25 (~2)", + "files_changed": 1 + }, + { + "ts": "2026-05-21T07:40:25Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-21 15:25 (~2)", + "files_changed": 1 } ] } diff --git a/.project.json b/.project.json index c2110ab..3f7ba59 100644 --- a/.project.json +++ b/.project.json @@ -78,6 +78,11 @@ "type" : "backend", "url" : "https:\/\/marketing.skg.com\/api" }, + { + "label" : "agent-cut-preview", + "type" : "app", + "url" : "http:\/\/2.24.28.41:4290\/agent\/" + }, { "label" : "git", "type" : "repo", diff --git a/RULES.md b/RULES.md index 6652f10..47957c5 100644 --- a/RULES.md +++ b/RULES.md @@ -15,6 +15,7 @@ ## 部署事实 - 平台:VPS `76.13.31.179`(Ubuntu 24.04 / Docker Compose / Coolify Traefik) +- Agent Cut 独立预览服务器:`2.24.28.41`(Ubuntu 24.04 / Docker Compose / 裸端口 `4290`),部署目录 `/opt/skg-marketing-studio`,Compose 入口 `docker-compose.standalone.yml`,访问地址 `http://2.24.28.41:4290/agent/`。该入口用于“一分钟二创出片终端”预览:用户只提交 TikTok 链接和产品图,后端 `AgentRun` 状态机负责下载、抽帧、规划、生成、自动重跑、审片和合成。 - 发布状态:已部署并验证(2026-05-20,主体元素按套图文件夹分组展示,主体生成接口提交后立即返回 queued 占位并后台逐视角生成、逐张回填;工作台外层取消 1800x1000 固定画布和应用层 `zoom` 缩放,改为正常流式桌面容器,最低操作宽度 1280px;源视频工作区主体链路为上方竖向参考帧池 + 宽幅对话式转换层、下方主体元素结果栏;转换层通过参考帧 `+` 加入、参考图分析、生图对话,英文 prompt 就绪后由发送区主按钮切换为确认生成,点击后才触发主体套图生成;转换层不再固定 640px 长高,按内容自然高度显示,仅以 560px 最大高度兜底内部滚动;下方主体元素结果栏的套图输出、轮询、文件夹分组、单张重生、删除和 hover 预览逻辑保持不变;胶片双击/拖拽加入参考帧池 + 胶片缓存复用 + 音频解析失败可重试,参考帧缩略图保持小尺寸 9:16 比例 + hover 左侧紧凑预览,旧主体模板区移出主路径 + 逐句时间轴移到原版视频下方并支持双行文案 + 波形同框时间对齐画面胶片 + 胶片密度按钮上移波形顶部 + 去分隔线 + 胶片上下错落 + body 顶层原位大放大 + 隐藏源视频工作区音频解析摘要卡 + 隐藏工作区顶部状态提示条 + 三字段候选生成工作流 + 折叠紧凑候选区);`https://marketing.skg.com` 已启用应用内登录页,未登录 API 返回 401,认证后首页 200;容器内 `/health` 返回 `ok:true` - 最近部署验证(2026-05-21):`8458dac` 已按“先本地 Docker、再上传部署”流程上线。上线前在本机 Docker 构建 `skg-marketing-studio-web:latest` / `skg-marketing-studio-api:latest`,并用本地 Compose 容器验证通过:`web:/ 302`、`web:/login/ 200`、`web:/_next/does-not-exist.js 404`、`web:/api/health 401`、`api:health ok`、`api:ytdlp_cookie_args []`、静态 bundle 包含 `未来健康 · 营销内容工作台` 和 `信息流广告复刻生产`,且未发现本地 API/dev URL 泄漏。随后通过 `./scripts/deploy-prod-safe.sh` 部署到 `/opt/skg-marketing-studio`;部署前备份为 `/opt/skg-marketing-studio-backups/skg-marketing-preserve-20260521070327.tgz`,生产 Docker 重建后脚本内验证通过(web/API 容器 Up、`/` 302、`/login/` 200、缺失 `_next` 资源 404、未登录 `/api/health` 401、容器内 `api:health ok`)。 - 最近部署验证(2026-05-20):`6597db3` 已通过 `./scripts/deploy-prod-safe.sh` 部署到 `/opt/skg-marketing-studio`;部署前备份为 `/opt/skg-marketing-studio-backups/skg-marketing-preserve-20260520151033.tgz`,生产 Docker 重建后脚本内验证通过(`web:/login/ 200`、`web:/api/health 401`、`api:health ok`)。线上登录后检查首页静态资源,当前加载 chunk `/_next/static/chunks/c48f07b9aef1cd29.js` 已包含 `min-w-[1280px]` 和 `max-w-[1920px]`,未再命中旧的 `h-[1000px]`、`w-[1800px]`、`BOARD_SCALE_PRESETS` 或 `boardScale`;对应工作台取消固定画布缩放,按浏览器正常流式布局渲染。 @@ -57,6 +58,7 @@ - 服务器目录:`/opt/skg-marketing-studio` - 生产部署唯一入口:`./scripts/deploy-prod-safe.sh`(先在服务器备份 `deploy/.env.production`、`data/jobs`、资源库和 `secrets`,再用受保护 rsync 同步代码,最后 Docker 重建并运行 `verify-prod-docker.sh`) - 生产容器重建命令:`docker compose -f docker-compose.prod.yml --env-file deploy/.env.production up -d --build`;只允许脚本内部或明确只重启容器时使用,不允许再用裸 `rsync --delete` 手动同步。 +- 独立预览容器重建命令:服务器 `/opt/skg-marketing-studio` 下执行 `docker compose -f docker-compose.standalone.yml --env-file deploy/.env.production up -d --build`;Web 暴露 `0.0.0.0:4290->80`,后端仅在 compose 内部网络暴露,`/api/` 由 Web 容器 Nginx 反代并复用应用内登录校验。 - 生产架构:`web` 容器用 Nginx 承载 Next 静态导出;`/login/`、`/_next/`、`/assets/`、`/skg-logo-black.svg`、`/oasis-source/` 等登录页必需静态资源公开访问;未登录访问工作台跳转 `/login/`,`/api/` 通过 Nginx `auth_request` 校验 FastAPI 会话 Cookie 后反代到 `skg-marketing-api:4291`;Traefik 通过 `coolify` 外部网络接入 80/443 - Web 验收必须以生产 Docker 形态为准:前端是 `next export` 静态产物 + Nginx,不是 `next dev` / `next start`。任何 Web 改动部署后必须运行 `./scripts/verify-prod-docker.sh`,确认 `/login/`、`/_next/`、`/api/health`、本地 API 地址泄漏和 API 镜像 `.env` 污染检查通过;不能只用本地 `npm run build` 作为上线依据。 - 当前音频解析:`https://ai.skg.com/azure/v1` 的 `gpt-4o-transcribe` 当前返回 `DeploymentNotFound`,且官方 Azure OpenAI transcription 路径探测也未返回可用部署;生产临时复制本地成功策略,直接使用容器内 `faster-whisper tiny.en` 真实转写,关闭 Gemini 多模态音频兜底。拿到真实 Azure ASR deployment 名后再恢复 `ASR_REMOTE_ENABLED=true`。 diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index be34247..be3b917 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -10,11 +10,13 @@ services: - ./deploy/.env.production environment: JOBS_DIR: /data/jobs + AGENT_RUNS_DIR: /data/agent_runs ASSET_LIBRARY_DIR: /data/asset_library PROMPT_LIBRARY_DIR: /data/prompt_library CORS_ORIGINS: https://marketing.skg.com volumes: - ./data/jobs:/data/jobs + - ./data/agent_runs:/data/agent_runs - ./data/asset_library:/data/asset_library - ./data/prompt_library:/data/prompt_library - ./data/_trash:/data/_trash diff --git a/docker-compose.standalone.yml b/docker-compose.standalone.yml new file mode 100644 index 0000000..9aa0817 --- /dev/null +++ b/docker-compose.standalone.yml @@ -0,0 +1,45 @@ +name: skg-agent-cut + +services: + api: + build: + context: . + dockerfile: Dockerfile.api + container_name: skg-agent-api + env_file: + - ./deploy/.env.production + environment: + JOBS_DIR: /data/jobs + AGENT_RUNS_DIR: /data/agent_runs + ASSET_LIBRARY_DIR: /data/asset_library + PROMPT_LIBRARY_DIR: /data/prompt_library + CORS_ORIGINS: http://2.24.28.41:4290,http://localhost:4290 + volumes: + - ./data/jobs:/data/jobs + - ./data/agent_runs:/data/agent_runs + - ./data/asset_library:/data/asset_library + - ./data/prompt_library:/data/prompt_library + - ./data/_trash:/data/_trash + - ./secrets/tiktok_cookies.txt:/run/secrets/tiktok_cookies.txt + restart: unless-stopped + networks: + - skg-agent-internal + + web: + build: + context: . + dockerfile: Dockerfile.web + args: + NEXT_PUBLIC_API_BASE: /api + container_name: skg-agent-web + depends_on: + - api + ports: + - "0.0.0.0:4290:80" + restart: unless-stopped + networks: + - skg-agent-internal + +networks: + skg-agent-internal: + name: skg-agent-internal