# Help Code02:Code Run / Page Data Dev 的 memindadm 运行时策略 > 文档版本:2026-07-23
> 状态:方案设计(未实施)
> 前置:[help-code01.md](./help-code01.md)(Aider 补充 Page Data 开发兜底)
> 关联:[memindadm-goose-gateway-design.md](./memindadm-goose-gateway-design.md) --- ## 1. 为什么要做 Phase 1.5 Phase 1 用 **env + VITE_ 构建期变量** 控制 code run 与 `page_data_dev` autodetect。这在 dev/staging 可用,但对「用户经常页面失败、插入失败」的运营场景不够: | 问题 | env/VITE 的局限 | |------|----------------| | 改开关要 rebuild H5 | `VITE_*` 打进 bundle,memindadm 点了不生效 | | 改开关要 SSH 改 `.env` | 103 Portal / worker 两套 env,易不一致 | | 无法按用户即时灰度 | 白名单改 env 无审计、无 UI | | 与现有 adm 能力分裂 | aider 能力已在 `h5_capability_grants`,策略却在 env | **目标:** 把 **「谁、哪种 task、是否 page_data_dev autodetect」** 迁入 memindadm;**部署拓扑**(worker 是否 spawn Aider)继续留 env。 --- ## 2. 配置分层(硬边界) ```mermaid flowchart TB subgraph adm ["memindadm 运行时策略(DB)"] P1[codeRun.enabled] P2[userAllowlist / roleAllowlist] P3[taskTypeAllowlist 含 page_data_dev] P4[pageDataDev.autodetect] P5[requireValidation] P6[generalCodeAutodetect] end subgraph env ["部署 env(不改或只读 override)"] E1[MEMIND_TOOL_GATEWAY_ENABLED] E2[AIDER_BIN / OPENHANDS_BIN] E3[worker 并发 / 超时 / guard] E4[MEMIND_AGENT_RUN_* 紧急 override] end subgraph cap ["已有用户能力(DB)"] C1[h5_capability_grants: aider/openhands] C2[h5_llm_executor_bindings] end adm --> Portal[agent-run-routes 校验] adm --> Auth["/auth/status → H5"] cap --> Portal env --> Worker[agent-run-worker] Portal --> Worker ``` ### 2.1 进 memindadm 的项 | 原 env / VITE | adm 字段 | 说明 | |---------------|----------|------| | `MEMIND_AGENT_CODE_RUNS_ENABLED` | `codeRun.enabled` | 后端是否接受 `tool_mode=code` | | `MEMIND_AGENT_CODE_RUNS_USER_IDS` | `codeRun.userAllowlist` | 空 = 不限制(enabled 时) | | `MEMIND_AGENT_CODE_RUN_TASK_TYPES` | `codeRun.taskTypeAllowlist` | 含 `page_data_dev`、`h5_chat_code_task` | | `MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION` | `codeRun.requireValidation` | 是否强制 receipt | | `VITE_AGENT_CODE_RUNS_ENABLED` | `codeRun.clientEnabled` | H5 是否展示/走 code 路径 | | `VITE_AGENT_CODE_RUNS_AUTODETECT` | `codeRun.generalAutodetect` | 通用代码语义 autodetect | | `VITE_AGENT_PAGE_DATA_DEV_AUTODETECT` | `pageDataDev.autodetect` | Page Data 修 bug 专用 autodetect | ### 2.2 继续留 env 的项 | env | 原因 | |-----|------| | `MEMIND_TOOL_GATEWAY_ENABLED` | worker 进程级;Portal 与 worker 故意不同值 | | `MEMIND_TOOL_GATEWAY_DEFAULT_EXECUTOR` | 机器上装的是 aider 还是 openhands | | `MEMIND_AGENT_RUN_QUEUE_CONCURRENCY` 等 | SLO / guard / LaunchAgent | | `MEMIND_AGENT_CODE_RUNS_*`(可选) | **紧急 override**:`MEMIND_CODE_RUN_POLICY_SOURCE=env` 时强制 env 优先 | --- ## 3. 数据模型 ### 3.1 表:`h5_agent_code_run_config` 与 `h5_skill_runtime_config`、`h5_image_make_admin_config` 同模式:`config_scope='global'` 单行 JSON。 ```sql CREATE TABLE IF NOT EXISTS h5_agent_code_run_config ( config_scope VARCHAR(32) PRIMARY KEY, config_json JSON NOT NULL, updated_by CHAR(36) NULL, updated_at BIGINT NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ``` ### 3.2 默认 JSON Schema ```json { "codeRun": { "enabled": false, "clientEnabled": false, "generalAutodetect": false, "requireValidation": true, "userAllowlist": [], "taskTypeAllowlist": [ "page_data_dev", "h5_chat_code_task", "page_edit_code_task" ] }, "pageDataDev": { "autodetect": false }, "meta": { "notes": "" } } ``` ### 3.3 生效优先级(与 Memory V2 adm 一致) 参考 `memory-v2-admin-config.mjs` 的 `FIELD_SPECS + env override` 模式: ```text 1. 若 MEMIND_CODE_RUN_POLICY_SOURCE=env → 仅读 env(紧急回滚) 2. 否则读 h5_agent_code_run_config(admin-db) 3. 若表为空且 MEMIND_AGENT_CODE_RUNS_ENABLED=1 → source=env-migration(兼容旧部署) 4. 否则 default(全 false,fail closed) ``` ### 3.4 用户级能力(不重复造表) 以下 **仍用现有表**,adm「Code Run 策略」页只读展示 + 链到用户能力编辑: - `h5_capability_grants`:`aider` / `openhands` - `h5_llm_executor_bindings`:Aider 模型绑定 - `h5_user_policies`:`code_delegate_executor`、`code_task_routing` **完整放行条件(与 today 相同,只是策略来源改为 DB):** ```text codeRun.enabled (adm) AND user ∈ allowlist(若配置) AND taskType ∈ taskTypeAllowlist AND capabilities.aider(用户 grant) AND executor binding 可用 AND(若 requireValidation)message 含 validation metadata AND toolGateway.enabled(env,worker 侧) ``` --- ## 4. 服务模块:`agent-code-run-admin-config.mjs` 建议新建,API 对齐 `skill-runtime-admin-config.mjs`: | 方法 | 用途 | |------|------| | `getAdminConfig()` | memindadm 编辑页 | | `updateAdminConfig(patch, { updatedBy })` | 保存 + 审计 | | `getRuntimeState()` | adm 运行时预览 | | `getEffectivePolicy({ userId })` | Portal 校验用 | | `getPublicClientPolicy({ userId })` | `/auth/status` 下发 H5 | ### 4.1 `getEffectivePolicy` 返回示例 ```json { "source": "admin-db", "updatedAt": 1753276800000, "enabled": true, "userAllowed": true, "taskTypes": ["page_data_dev", "h5_chat_code_task", "page_edit_code_task"], "requireValidation": true, "pageDataDevAutodetect": true, "generalAutodetect": false } ``` ### 4.2 `getPublicClientPolicy` 返回示例(按用户过滤后) ```json { "codeRun": { "enabled": true, "pageDataDevAutodetect": true, "generalAutodetect": false } } ``` 未登录或用户不在 allowlist 时:`codeRun.enabled=false`(或不返回该块)。 --- ## 5. HTTP API ### 5.1 memindadm(`admin-routes.mjs`) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/admin/agent-code-run/config` | 读配置 + source + updatedBy | | PUT/PATCH | `/api/admin/agent-code-run/config` | 更新 | | GET | `/api/admin/agent-code-run/runtime` | 有效策略 + env 覆盖状态 + worker 只读摘要 | Worker 摘要可代理现有 `/api/runtime/status` 的 `toolRuntime.codeRunPolicy` 与 `queue`(**只读**,不在 adm 改 worker env)。 ### 5.2 Portal 用户面 **扩展 `GET /auth/status`**(已登录用户): ```json { "authenticated": true, "user": { "...": "..." }, "capabilities": { "aider": true, "...": "..." }, "skillRuntime": { "...": "..." }, "agentCodeRun": { "enabled": true, "pageDataDevAutodetect": true, "generalAutodetect": false } } ``` **扩展 `POST /api/agent/runs` 校验:** 从 `getEffectivePolicy(userId)` 读,不再只读 `process.env.MEMIND_AGENT_CODE_RUNS_*`。 ### 5.3 只读运维 `GET /api/runtime/status` 增加: ```json { "toolRuntime": { "codeRunPolicy": { "source": "admin-db", "enabled": true, "userAllowlist": [], "taskTypeAllowlist": ["page_data_dev", "..."], "requireValidation": true, "pageDataDevAutodetect": true, "envOverrideActive": false } } } ``` --- ## 6. 前端改造(去掉 VITE_ 硬依赖) ### 6.1 `src/utils/agentRunMode.ts` ```typescript // 优先级:runtime policy(/auth/status)> VITE_(dev fallback) let runtimePolicy: AgentCodeRunClientPolicy | null = null; export function applyAgentCodeRunClientPolicy(policy: AgentCodeRunClientPolicy | null) { runtimePolicy = policy; } function clientCodeRunsEnabled(): boolean { if (runtimePolicy?.codeRun?.enabled != null) return runtimePolicy.codeRun.enabled; return agentCodeRunsEnabled; // VITE fallback } function clientPageDataDevAutodetect(): boolean { if (runtimePolicy?.codeRun?.pageDataDevAutodetect != null) { return runtimePolicy.codeRun.pageDataDevAutodetect; } return agentPageDataDevAutodetectEnabled; } ``` ### 6.2 注入时机 在现有 `/auth/status` 加载处(如 `src/api/client.ts` 或 auth hook): ```typescript const status = await fetchAuthStatus(); applyAgentCodeRunClientPolicy(status.agentCodeRun ?? null); ``` **效果:** memindadm 打开 `pageDataDev.autodetect` 后,用户刷新页面即生效,**无需 rebuild H5**。 --- ## 7. memindadm UI(Ops 后台) 建议菜单位置:**系统 / Agent 运行时 → Code Run & Page Data Dev** | 控件 | 类型 | 说明 | |------|------|------| | Code Run 总开关 | toggle | `codeRun.enabled` | | H5 客户端启用 | toggle | `codeRun.clientEnabled` | | Page Data Dev Autodetect | toggle | `pageDataDev.autodetect` | | 通用 Code Autodetect | toggle | `codeRun.generalAutodetect`(默认关) | | 强制 Validation | toggle | `codeRun.requireValidation` | | 用户白名单 | multi-select UUID | 空 = 全部(enabled 时) | | Task Types | checkbox list | 至少含 `page_data_dev` | | 当前 Worker 状态 | read-only | 来自 `/runtime/status` | | Env Override 警告 | banner | `MEMIND_CODE_RUN_POLICY_SOURCE=env` 时显示 | **保存时:** 写 `updated_by` + `updated_at`;可选写 admin audit log(与 image-make 一致)。 --- ## 8. 迁移与兼容 ### 8.1 首次上线 1. 建表 `h5_agent_code_run_config`,默认全 `false` 2. 部署 `agent-code-run-admin-config.mjs` + admin API 3. **迁移脚本**(可选):若 env 已开启,import 到 DB 并提示改 `POLICY_SOURCE=admin` ```bash node scripts/migrate-agent-code-run-config-from-env.mjs --dry-run node scripts/migrate-agent-code-run-config-from-env.mjs --apply ``` ### 8.2 回滚 | 场景 | 操作 | |------|------| | adm 配错了 | memindadm 关 `codeRun.enabled` | | 紧急全站关闭 | `MEMIND_CODE_RUN_POLICY_SOURCE=env` + unset `MEMIND_AGENT_CODE_RUNS_ENABLED` | | worker 异常 | LaunchAgent 停 worker(现有 runbook),与 adm 无关 | ### 8.3 与 help-code01 Phase 的关系 | Phase | 内容 | 配置来源 | |-------|------|----------| | Phase 1 ✅ | `page_data_dev` 意图 + autodetect 逻辑 | env/VITE | | **Phase 1.5** | adm 运行时策略 + `/auth/status` | **DB + adm UI** | | Phase 2 | verify → Aider dev loop 脚本 | 脚本 + adm 开关 | --- ## 9. 实施清单(Phase 1.5) - [x] `agent-code-run-admin-config.mjs` + 单测 - [x] `admin-routes.mjs`:`/agent-code-run/config`、`/runtime` - [x] `server.mjs`:`/auth/status` 增加 `agentCodeRun` - [x] `agent-run-routes.mjs`:改用 `getEffectivePolicy(userId)` - [x] `agentRunMode.ts`:runtime policy 优先于 VITE_ - [x] Ops UI 页面(表单 + JSON 高级编辑:`/ops/admin/agent-code-run`) - [x] `migrate-agent-code-run-config-from-env.mjs` - [x] 更新 `docs/agent-run-worker-rollout-runbook.md` - [x] `.env.example` 增加 `MEMIND_CODE_RUN_POLICY_SOURCE` - [x] verify:`agent-code-run-admin-config.test.mjs` + 扩展 `chat-agent-run-gate.test.mjs` --- ## 10. 安全与审计 1. **仅 admin 可写** — 复用 `requireAdmin` 2. **默认 fail closed** — 新环境 adm 配置为空 = 全关 3. **双闸门保留** — adm 开 + 用户 `aider` grant + worker gateway env 4. **审计字段** — `updated_by`、`updated_at`;重要变更写 admin audit 5. **生产建议** — 先 `userAllowlist` 小范围开 `page_data_dev`,再扩 `generalAutodetect` --- ## 11. 相关文件索引 | 类型 | 路径 | |------|------| | 方案总览 | `docs/help-code01.md` | | Goose 网关规划 | `docs/memindadm-goose-gateway-design.md` | | 可复用 adm 模式 | `skill-runtime-admin-config.mjs` | | env↔adm 映射先例 | `memory-v2-admin-config.mjs` | | 后端 code run 门禁 | `agent-run-routes.mjs` | | 前端 autodetect | `src/utils/agentRunMode.ts` | | 运行时只读 | `server.mjs` → `runtimeCodeRunPolicyStatus()` | | Worker runbook | `docs/agent-run-worker-rollout-runbook.md` | --- ## 12. 一句话总结 **memindadm 管「策略」(谁、哪种 task、是否 page_data_dev);env 管「部署」(worker 是否 spawn Aider);H5 从 `/auth/status` 读运行时策略,不再依赖 rebuild VITE_。**