229 lines
9.1 KiB
Markdown
229 lines
9.1 KiB
Markdown
# 本地开发
|
||
|
||
> 这是本机本地开发文档,只处理当前工作区里的源码联调,不做任何生产同步。
|
||
> `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
|
||
的短期 token,MindSpace 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 runtime,Portal 会 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`。这相当于运行时止血;如果确认整版不要,再按代码回撤处理。
|