Files

229 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 本地开发
> 这是本机本地开发文档,只处理当前工作区里的源码联调,不做任何生产同步。
> `pnpm dev` 不再启动 Plaza;如果需要联动 Plaza,请显式运行 `pnpm dev:all`,或者单独运行 `pnpm dev:plaza` / `pnpm start:plaza`。
> Plaza 专用脚本的源码默认指向同级仓库 `../memind_plaza`;如你的目录不同,请用 `PLAZA_APP_DIR` 覆盖。
> 生产 / 测试 / 预览隔离仍单独看 [生产 / 测试 / 预览隔离规程](./service-isolation-runbook.md)。
`pnpm dev` 启动后,用 **127.0.0.1 + 端口** 访问本仓库自己的服务:
| 服务 | 地址 |
|------|------|
| MindSpace H5 | http://127.0.0.1:5173/?preview=mindspace |
| Ops 审核后台 | http://127.0.0.1:3002/ops/ |
| API / Portal | http://127.0.0.1:8081 |
| memind_adm | http://127.0.0.1:8082 |
| Plaza | http://127.0.0.1:3001/plaza |
```bash
pnpm install
cp .env.example .env
pnpm dev
pnpm open:local-test # 浏览器打开 H5
```
### H5 多个接口同时返回 500
如果 `5173` 页面里的 `/auth/status``/auth/wechat/config``/api/analytics/context`
同时返回 `text/plain` 500,先检查 Portal
```bash
curl -i http://127.0.0.1:8081/auth/status
```
`8081` 无法连接表示 Vite 还在运行、但它代理的 Portal 已退出,并非这些路由同时故障。
前台 `pnpm dev` 会在任一受管子进程意外退出时结束整个开发栈;重新运行 `pnpm dev`
即可干净启动。LaunchAgent 模式则查看 `~/Library/Logs/memind-dev.log` 并按下节命令重启。
### LaunchAgent 常驻(推荐本机联调)
终端里跑 `pnpm dev` 会在 Cursor / 终端关闭时被 SIGTERM 停掉。若希望登录后自动拉起、掉线自恢复,可安装 LaunchAgent(与 imgproxy / goosed 同类):
```bash
pnpm setup:dev-launchagent
# 卸载
pnpm setup:dev-launchagent:uninstall
```
| 项 | 值 |
|----|-----|
| Label | `cn.tkmind.memind-dev` |
| 进程 | portal (8081) + memind_adm (8082) + Ops (3002) + Vite (5173) |
| 日志 | `~/Library/Logs/memind-dev.log` |
安装后仍可用 `pnpm dev` 做前台调试;两者不要同时占用同一端口。重启服务:
```bash
launchctl kickstart -k gui/$(id -u)/cn.tkmind.memind-dev
```
需要旧式全栈联动时,改用:
```bash
pnpm dev:all
```
## 环境变量
| 变量 | 默认 | 说明 |
|------|------|------|
| `H5_PORT` | 8081 | Portal / API |
| `VITE_PORT` | 5173 | MindSpace 前端 |
| `PLAZA_PORT` | 3001 | Plaza |
| `OPS_PORT` | 3002 | Ops SPA |
| `ADMIN_PORT` | 8082 | memind_adm |
| `H5_PUBLIC_BASE_URL` | http://127.0.0.1:5173 | 公开链接基址 |
| `PLAZA_APP_DIR` | ../memind_plaza | Plaza 专用脚本的源码路径(`pnpm dev:plaza` / `pnpm start:plaza` / `pnpm dev:all` |
| `MEMIND_SESSION_BROKER_ENABLED` | `0`(未设置) | Session Broker 灰度开关;Patch 2+ 本地验证时可设 `1`,见 [H5 Session 架构](./h5-session-architecture-20260706.md) |
### MindSpace:本地 vs 生产(必须区分)
`pnpm dev` / `server.mjs` 启动时会读取 `MEMIND_RUNTIME_PROFILE`(见 `scripts/memind-runtime-profile.mjs`):
| `MEMIND_RUNTIME_PROFILE` | 用途 | MindSpace 实现 |
|--------------------------|------|----------------|
| `local`(**默认** | 本机日常开发 | Portal 内置 `MINDSPACE_SERVER_ADAPTER=local` |
| `split-service` | 本机验证 103 拆分架构 | `remote``http://127.0.0.1:8082` 独立 MindSpace 服务 |
| `production` | **仅 103 服务器** | 不覆盖 `.env`,以服务器配置为准 |
**本地 `.env` 推荐:**
```bash
MEMIND_RUNTIME_PROFILE=local
```
**本机要测 split-service 时:**
```bash
MEMIND_RUNTIME_PROFILE=split-service
MINDSPACE_REMOTE_BASE_URL=http://127.0.0.1:8082
MINDSPACE_REMOTE_AUTH_TOKEN=local-dev-secret # 必须与 MindSpace LaunchAgent 一致
launchctl kickstart -k "gui/$(id -u)/cn.tkmind.mindspace-service"
pnpm dev
```
如需验证 Goose 的逻辑 workspace MCP,再让 Portal 与 MindSpace Service
使用相同的本地签名 secret;该值至少 16 个字符,只放本机 `.env`
不得提交:
```bash
MINDSPACE_MCP_BASE_URL=http://127.0.0.1:8082
MINDSPACE_MCP_TOKEN_SECRET=replace-with-a-local-secret
# 可选;默认 12 MiB,必须大于等于 1024
MINDSPACE_MCP_MAX_BODY_BYTES=12582912
```
Portal 用 secret 签发绑定 user/session/package/workspace/tool allowlist
的短期 tokenMindSpace Service 用同一 secret 验证;Goose extension
只收到 scoped token,不会收到签名 secret。该 MCP 配置目前用于
`split-service` 联调。配置完整时 DOCX 目标写入和长图渲染也会经过
MindSpace Service;未配置时不会开放 `publish_page`,其它工具保留
本地兼容行为。
验证当前源码的本地 split-service 链路可运行:
```bash
npm run smoke:mindspace-split-service
```
该 smoke 会构建本地 `.runtime/mindspace-service`、启动临时独立
MindSpace RPC 服务,并通过 remote adapter 验证 health/contract、
workspace 写读、微信 HTML 交付与 fresh thumbnail;不会发布或上传
runtime artifact。它会读取本机配置的开发数据库并创建唯一的
`split-service-smoke-*` session/package 记录,退出时会清理对应
package/artifact,并把临时文件根删除。
remote adapter 会在 Portal 启动时校验 `/mindspace/v1/contract`
`contractVersion`、required capabilities 与关键 binding。如果本机
`8082` 仍是旧 MindSpace runtimePortal 会 fail-fast,而不是等到
页面交付时才出现 `Unknown binding`
排查 package / artifact / public URL 链路:
```bash
npm run audit:conversation-packages -- --limit 100
npm run trace:mindspace-artifact -- --public-url http://127.0.0.1:5173/MindSpace/<owner>/public/page.html
```
启动后 Portal 日志应出现:`[Portal] Runtime profile: MEMIND_RUNTIME_PROFILE=local, MINDSPACE_SERVER_ADAPTER=local, ...`
**禁止:** 把 103 生产 `.env`、RDS 连接串、`MINDSPACE_REMOTE_AUTH_TOKEN` 生产值复制进本机 Git 仓库。
### H5 Session 架构本地全量联调(`0706-bug干净` 分支)
**本机 `.env`**(勿提交 Git)打开下列开关后重启 `pnpm dev`
```bash
MEMIND_SESSION_BROKER_ENABLED=1
MEMIND_ROUTER_NORMALIZED_DECISION=1
MEMIND_SSE_EVENT_TAXONOMY=1
MEMIND_RUN_STREAM_REPLAY=1
MEMIND_H5_HTML_FINISH_GUARD=1
```
| 开关 | 验证点 |
|------|--------|
| `MEMIND_SESSION_BROKER_ENABLED` | Portal 启动日志、`sessionAccess` 路径 |
| `MEMIND_SESSION_BROKER_METRICS` | `[session_broker.*]` structured log(§13.4 |
| `MEMIND_ROUTER_NORMALIZED_DECISION` | gateway 读 `decision.route` / `session_hint``shadow` 仅打 `[router-shadow]` 日志 |
| `MEMIND_SSE_EVENT_TAXONOMY` | SSE payload 多 `taxonomy` 字段 |
| `MEMIND_RUN_STREAM_REPLAY` | run SSE 含 `id:`,断线重连补发 |
| `MEMIND_SESSION_STREAM_REPLAY` | session SSE 持久化 + Last-Event-ID 重连补发(4c |
| `MEMIND_H5_HTML_FINISH_GUARD` | Finish 后假交付检测 / 自动 repair |
启动后应看到类似:
```text
[Portal] H5 session flags: MEMIND_SESSION_BROKER_ENABLED, ...
```
回归:
```bash
npm run verify:h5-session-patches
# 内含:单测、§5.7 session broker coverage、goosed proxy boundary、MindSpace publish guards
```
手工 soak 清单(全量开发完成后执行):[pending-fixes/h5-local-soak-20260706.md](./pending-fixes/h5-local-soak-20260706.md)
关闭某项:对应变量改 `0` 或删除后重启 dev。
Plaza 本地开发说明见 [plaza-local.md](./plaza-local.md)。生产发布、同步与回滚不要在这里处理,统一看 [生产更新发布指南](./release-deploy.md)。
### 本地 `.env` 与 103 生产 `.env` 分离
| 项 | 本地(本机 `.env` / `../../.env.local` | 103 生产(服务器 `/Users/john/Project/Memind/.env` |
|---|---|---|
| 配置真相 | 复制 `.env.example`,只填本地联调值 | 仅在 103 维护,**不提交 Git** |
| `TKMIND_API_TARGET` | 通常单实例 `https://127.0.0.1:18006` | 9 个 goosed target`18006``18014`),见 [103 runtime topology](./103-runtime-topology.md) |
| `H5_PUBLIC_BASE_URL` | `http://127.0.0.1:5173` | `https://m.tkmind.cn` |
| `MEMIND_SESSION_BROKER_ENABLED` | Patch 2 起可本地设 `1` 验证 | 灰度窗口由运维在 103 `.env` 单独开启 |
| RDS / Redis | 可连本地 MySQL 或留空 | 生产 RDS + Redis,见 103 `.env` |
硬规则:不要把 103 的 `.env`、密钥、RDS 连接串复制进仓库;`.env.example` 只记录变量名与本地示例值。
## 公众号 Agent 调试
服务号消息转发到专属 Agent 这条链路默认关闭,只有显式设置下面这些变量后才会启用:
- `H5_WECHAT_MP_ENABLED=1`
- `H5_WECHAT_MP_APP_ID`
- `H5_WECHAT_MP_APP_SECRET`
- `H5_WECHAT_MP_TOKEN`
服务号后台需要把服务器地址指向:
```text
{H5_PUBLIC_BASE_URL}/webhooks/wechat-mp/messages
```
当前版本只支持“明文模式”回调,不支持 `aes` 安全模式解密。要保证 H5 微信 OAuth 和公众号消息使用同一个服务号 `AppID`,这样消息里的 `openid` 才能直接命中已绑定用户。
如果要立即停用这版,不改代码也可以先把:
```bash
H5_WECHAT_MP_ENABLED=0
```
然后重启 `server.mjs`。这相当于运行时止血;如果确认整版不要,再按代码回撤处理。