核心能力 · Five Capabilities
所有能力围绕一条主线:账号(pubaccount) → writing-kit 模板 → 5 步向导 → 流式 AI 双稿 → 发布。账号本身即上下文,作者从扫码进站到点发送全程不离开 echo。
架构 · Users → echo → 3 deps
受众通过两个入口进:微信内置浏览器(扫码登录后留在公众号生态)或桌面浏览器(直接访问域名)。echo 单实例对接三个外部依赖:AI 推理、微信登录、部署 / 数据库 host。
SSE 流式
扫码登录 + openid 绑定
共享 PG host · Caddy HTTPS
关键里程碑 · Timeline
从 Phase 1 脚手架到 8M batch 图生上线,每个 phase 独立可发布。⭐ 标记的是结构性里程碑:Phase 2.0 schema 落地 / 2.3 AI 流式接入 / 2.5 微信扫码登录 / 8M 图生 batch。
名场面 · 1 个最值钱的坑(深度)
Phase 2.5 扫码登录刚接上 wx-gateway 那天,本地完美、桌面 Chrome 完美,一进微信内置浏览器立刻挂 — 扫码后状态条永远 pending,从不进 confirmed。最初以为是 SSE 命名事件没监对,改完发现还有第二拳:反代后 req.url 拼回调直接拼成内网 URL。
SSE 默认事件名 + 反代后 req.url 不可信
- 症状
- 扫码登录在生产微信内置浏览器表现:二维码刷新正常、用户扫码后微信 toast 确认成功,前端 SSE 状态条永远 pending,从不切到 confirmed,也不重定向。本地 dev / 桌面 Chrome 全绿。
- 根因 1
- 前端用 eventSource.addEventListener('confirmed', ...) 监听命名事件。但 wx-gateway 那边 SSE 发出来的是 默认 message 事件(payload 里带 type 字段区分),根本没写 event: confirmed 这一行。命名 listener 永远收不到,自然永远 pending。
- 修法 1
- 统一改成 onmessage + payload 内部分发:e => JSON.parse(e.data).type === 'confirmed' && finalize()(be8bdb0)。
- 根因 2
- 修完命名事件,confirmed 收到了,可 finalize 后重定向到内网 IP。原因是 callback 用 new URL(path, req.url) 拼 absolute URL,反代后 Next 看到的 req.url 是 http://127.0.0.1:3795/...,不是外网域。
- 修法 2
- 改用 process.env.NEXTAUTH_URL 显式拼绝对 URL(496dedb),反代环境下 req.url 一律视为不可信。
// 拳 1 — 前端 SSE 监听:别用命名事件 - eventSource.addEventListener('confirmed', e => ...) + eventSource.onmessage = e => { + const m = JSON.parse(e.data) + if (m.type === 'confirmed') finalize(m) + } // 拳 2 — 拼回调 URL:别信反代后的 req.url - return NextResponse.redirect(new URL('/dashboard', req.url)) + const base = process.env.NEXTAUTH_URL! + return NextResponse.redirect(new URL('/dashboard', base))
📊 当前现状 · Status
不写"运行良好 / 反馈正面"这类空话。下面五个分组每条都能在 git log / src/db/schema.ts / .hermes/memory.md 里 grep 到。
生产部署
- 域名:echo.mvp.restry.cn · 已上线 · HTTPS by Caddy
- PM2 进程:echo · 端口 3795 · /opt/mvp-apps/echo/
- 部署链路:mvp-deployer zip → 异步 build → drizzle migrate → seed:kits
- build 顺序硬绑死:drizzle-kit migrate → pnpm seed:kits → next build,少一步炸
- env 切换:postDeploy ln -sf .env .env.local(drizzle.config.ts 读 .env.local)
数据规模
- 9 张 ec_* 表(src/db/schema.ts):ec_users · ec_sessions · ec_accounts_oauth · ec_verification_tokens
- 内容域:ec_pubaccounts · ec_articles · ec_writing_kits · ec_article_assets · ec_settings
- Postgres:本地 192.168.1.235:15432/echo · 生产 127.0.0.1:5432/echo(共享 host)
- schema 状态机:ec_article_status · ec_asset_status · ec_asset_platform 三个 enum
- writing-kit seed:5min-ai 模板已 vendor 进 scripts/writing-kits/5min-ai/(7e2e784)
接入依赖
- wx-gateway:业务方 echo 已注册;扫码登录走 /wx/qr/echo + SSE poll
- Azure OpenAI:文本 gpt-5.4 流式改写;图像 gpt-image-2(8M batch 接入)
- 门神 vault:1a83b66 接入;所有密钥 vault project show echo,禁读 ~/.credentials/.env
- mvp-deployer:zip-only 上传 + 异步 build + 共享 PG host
最近变动(8 条)
- 56a7f17 docs(.hermes): project memory + SKILL prod status fix
- 1a83b66 docs: 接入门神 vault;.env.local* 加 gitignore
- dc1f1a9 docs: dark architecture diagram (SVG/HTML)
- c6fd21d fix(delete): native confirm + router.replace+refresh
- fdae06b feat(echo): 8M batch — 图生 + 设置页 + UX cleanup ★
- be8bdb0 fix(wx-login): SSE uses default message event
- e9b829b feat(ai-draft): 5 步公众号写作向导 + A/B 改写
- 8052769 fix(mobile+session): 移动端响应式 + jwt 按需 DB 刷新
运维状态
- Phase 2.5 扫码登录已稳定:命名事件 + 反代 URL 双拳修复后,生产微信内置浏览器登录链路一个月零工单
- 8M batch 图生已上线:gpt-image-2 直接进编辑器,作者不再切到外部出图工具
- 移动端响应式跑通:sidebar / dashboard / header 一套适配;jwt 按需 DB 刷新拿 name/image
- main 干净:git status 无 stash 无 WIP,本地与生产同步
- 已知警告:metadataBase 没配,next build 会 warn(P2 排期)
🚧 未结清债务 · Open Debt
来源:.hermes/memory.md TODO 段、SKILL.md 过时项、近 22 commits 标记。每条 4 列:优先级(P0 立刻 / P1 本周 / P2 排期) · 工作量(S < 0.5d · M 1-2d · L 3d+) · 待办 · 现状是什么。
| 优先级 | 工作量 | 待办 | 现状(还差什么) |
|---|---|---|---|
| P1 | S | SKILL.md "未部署" 文案过时 | .hermes/memory.md 已标注:.hermes/skills/echo/SKILL.md 里写"未部署",但 echo.mvp.restry.cn 早已上线。需改成"已上线"+ 端口 / 部署链路一句话。 |
| P1 | S | TODO.md 清理 | 老 TODO 里列的 references / style-fingerprint 已落到 scripts/writing-kits/5min-ai/ 实际目录,TODO 文档没同步删掉。需逐项核对、删冗余。 |
| P1 | M | 公众号定时推送 | 当前发布只支持"直接推 / 存草稿",Phase 3 列的定时推送没动:需 ec_articles.scheduled_at 字段 + cron 扫描 + wechat-publisher 调度链路。 |
| P1 | L | 小红书一稿多投 | Phase 3 主目标。ec_asset_platform enum 已留好 xhs 占位,但发布链路 + 排版适配 + 平台 token 接入全空。 |
| P2 | S | metadataBase 配置 | next build 持续 warn,OG image 拼绝对 URL 不准。一行 layout.tsx 加 metadataBase: new URL('https://echo.mvp.restry.cn') 就完。 |
| P2 | M | 视频生成 | Phase 3 三大目标之一。需调研短视频 AI 生成 API + 排版 + 公众号视频号发布链路,目前无任何代码。 |
| P2 | S | 多账号真实接入 | ec_pubaccounts 表 schema 已支持挂多个公众号,但目前只有一个真实账号在跑。新账号接入流程没走过一遍,可能有未发现的 hard-code。 |