Files
mnote/design/07-ai/process/7-41-page-ai-hermes-reasonix-user-profile-isolation-v2.md
T

17 KiB
Raw Blame History

7-41 Page AI Hermes / Reasonix user profile isolation v2

创建时间:2026-05-29

状态:process

OwnerPage AI agent identity / Hermes profile policy / Reasonix memory policy

上位依据:

  • design/07-ai/done/7-39-page-ai-agent-selector-context-authorization-settings-v1.md
  • design/07-ai/done/7-40-page-ai-context-envelope-and-run-receipt-v1.md
  • design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md
  • design/07-ai/process/7-38-page-ai-sidebar-runtime-owner-split-v1.md

参考依据:

  • Hermes 官方 profile 文档:profile 是独立 Hermes home,包含 config.yaml.envSOUL.md、memories、sessions、skills、cron、state database、gateway state。
  • Hermes WebUI:技能 toggle 直接写 profile config.skills.disabled
  • Hermes VSCode:只管理会话和一次性上下文建议,不提供真正的 per-user skill disable。
  • PilotDeck:以 WorkSpace 为边界隔离文件、记忆和技能,并强调白盒记忆可追溯。
  • Reasonix 文档/本地实现:默认使用 ~/.reasonix/memory/global~/.reasonix/memory/<project-hash>REASONIX_MEMORY=off|false|0 可关闭 memory 注入。

1. 背景

7-39 已把 Page AI UI 收口为 agent selector + contextRefs + SQLite per-user preference。7-40 进一步把 MNote skill library 定位为 agent 可按需读取的能力摘要,而不是每轮强行注入 prompt。

但当前 Hermes skill/profile 的真实边界仍不正确:

  • Hermes 的 skills.disabled 是 profile 级配置,不是 MNote 用户级偏好。
  • Hermes profile 自带 SOUL.md、memory、session、skills 和 state;多个 MNote 用户共用同一个可写 profile,会把个人偏好、记忆和技能配置混在一起。
  • 当前 Page AI UI 已经能展示 Hermes skill toggle,但普通用户如果直接写共享 Hermes profile,就会影响其它用户。
  • Reasonix 虽然不像 Hermes 那样有 SOUL 人格,但它也有 global/project memory。默认共享 ~/.reasonix 时,不能假设完全无状态。

因此本稿把 Page AI agent identity 从“选择 Hermes / Reasonix”提升为“选择 agent + profile scope + memory policy”。

2. 产品决策

2.1 Hermes profile 分层

Hermes profile 分为两类:

profile kind owner 普通用户能否使用 普通用户能否改 skill memory/session
personal 单个 MNote 用户 能,仅限自己的 profile 用户独立
shared 系统 / 管理员 能,若管理员公开 不能 默认不写入用户私有长期记忆

初始共享 Hermes profile 只包含 lite

要求:

  • 每个 MNote 用户可以访问自己的 personal Hermes profile。
  • 每个 MNote 用户可以访问被管理员公开的 shared Hermes profile。
  • shared Hermes profile 的 skill/config 只有管理员能改。
  • personal Hermes profile 的 skill/config 只有该 profile owner 或管理员能改。
  • Page AI 发送请求时必须携带解析后的 agentProfileRef,不能只携带裸 profile=lite

2.2 MNote 内置技能开关

MNote 内置 skill / tool 属于 MNote 自己的能力面,普通用户应该可以按用户启停。该开关不写 Hermes profile,而是写 SQLite control-plane。

含义:

  • mnote_builtin_skill_enabled 是 per-user 偏好和服务端执行策略,必须按当前 SQLite 用户隔离。
  • hide_builtin_skills=true 只是 UI 展示偏好,用于折叠或隐藏 MNote 内置能力说明;它不等于禁用。
  • MNote tool 是否可调用由服务端根据 user_id + agentId + contextRefs + allowedRoots + mnote_builtin_skill_enabled 决定。
  • 普通用户可启停自己的 MNote 内置 skills;管理员可设置默认值或全局禁用策略。
  • MNote 内置 skill 开关不修改 Hermes profile config.yaml,也不影响 shared Hermes profile。

2.3 Hermes profile skills

可以配置的只有 Hermes profile 自己的 skills。

规则:

  • personal profile:用户可启停该 profile 下的 Hermes skills,写入该 personal profile 的 config.yaml
  • shared profile:普通用户只读;管理员可启停 shared profile skills。
  • skill toggle API 必须做服务端权限检查,不能只靠 UI 禁用按钮。
  • MNote 不再把 ai.agent.hermes.profile.<name>.skills.enabled 当成普通用户对共享 profile 的安全开关;MNote 内置 skill 的 per-user 开关应使用独立 SQLite key。

2.4 Reasonix memory policy

Reasonix 默认关闭 memory 注入。

规则:

  • 默认启动 Reasonix ACP 时设置 REASONIX_MEMORY=off
  • 每个 MNote 用户可在设置中开启 Reasonix memory。
  • 该设置保存到 SQLite user_ui_preferences,按用户隔离。
  • 开启后,UI 需明确标注 Reasonix 将使用 global/project memory。
  • 第一阶段不强制给 Reasonix 每用户独立 HOME;若后续需要更强隔离,再增加 reasonix_home_mode=per_user

3. 数据合同

3.1 Agent profile ref

Page AI payload 中新增或固定以下结构:

{
  "agentId": "hermes",
  "agentProfileRef": {
    "kind": "personal",
    "profileId": "usr_123_default",
    "ownerUserId": "usr_123",
    "baseProfile": "default",
    "displayName": "我的 Hermes"
  }
}

shared profile

{
  "agentId": "hermes",
  "agentProfileRef": {
    "kind": "shared",
    "profileId": "shared_lite",
    "ownerUserId": null,
    "baseProfile": "lite",
    "displayName": "Lite"
  }
}

服务端要求:

  • 不接受浏览器直接提交任意 Hermes filesystem path。
  • profileId 必须由 SQLite control-plane 解析到当前用户可访问的 profile。
  • 对 personal profile,当前用户必须是 owner 或 admin。
  • 对 shared profile,必须是公开 profile 或 admin。
  • 所有 run / skill list / skill toggle / settings read 都通过 agentProfileRef 解析,不走裸 profile name。

3.2 SQLite control-plane

建议新增控制面表,避免只用偏好 key 表达权限关系:

ai_agent_profiles
- id
- agent_id                 # hermes
- profile_kind             # personal | shared
- owner_user_id            # personal 必填,shared 为空
- base_profile_name        # Hermes 原始 profile 名或模板名
- isolated_profile_name    # MNote 管理后的真实 Hermes profile 名
- display_name
- status                   # active | disabled
- created_at
- updated_at

ai_agent_profile_grants
- profile_id
- user_id
- role                     # owner | user | admin
- can_run
- can_manage_skills
- can_manage_config
- created_at
- updated_at

第一阶段也可以在现有 user_ui_preferences 中保存默认选择:

  • ai.agent.hermes.default_profile_id
  • ai.agent.hermes.hide_builtin_skills
  • ai.agent.mnote_builtin.skills.enabled
  • ai.agent.reasonix.memory_enabled

但 profile 权限、owner、shared/personal 类型不应只存在于 UI preference。

MNote 内置 skill 的用户级开关可以第一阶段存在 user_ui_preferences,但服务端 tool policy 读取时必须视为执行策略,而不是纯 UI 状态。若后续需要审计、管理员默认值或组织策略,应升级为独立表:

ai_user_skill_preferences
- user_id
- skill_id
- enabled
- updated_at

3.3 Hermes profile provisioning

创建 personal Hermes profile 时:

  • 可从共享模板复制 config.yaml.envSOUL.md 和 skills。
  • 不复制 memories、sessions、state database、gateway state。
  • 生成的真实 profile name 必须包含 MNote 用户隔离标识,例如 mnote-u-<userId>-default
  • provisioning 过程由服务端执行,并记录到 SQLite control-plane。

shared lite

  • 初始由管理员登记为 shared_lite
  • 普通用户只可 run / list readonly。
  • 管理员可改 skill/config。

4. API 合同

4.1 Profile list

GET /api/ai/agent-profiles?agentId=hermes

返回当前用户可访问 profiles

{
  "profiles": [
    {
      "profileId": "usr_123_default",
      "kind": "personal",
      "displayName": "我的 Hermes",
      "canRun": true,
      "canManageSkills": true
    },
    {
      "profileId": "shared_lite",
      "kind": "shared",
      "displayName": "Lite",
      "canRun": true,
      "canManageSkills": false
    }
  ]
}

4.2 Skill list

GET /api/hermes/client/skills?profileId=...

要求:

  • personal profile 返回可 toggle 状态。
  • shared profile 对普通用户返回 readonly 状态。
  • MNote 内置 skills 返回值必须标记 builtin=trueconfigurable=trueconfigScope=user_sqlite
  • Hermes profile skills 标记 builtin=falseconfigurable=canManageSkills

4.3 Skill toggle

PUT /api/hermes/client/skills/toggle

请求:

{
  "profileId": "usr_123_default",
  "skillName": "writer",
  "enabled": false
}

服务端必须:

  • 解析 profileId
  • skillKind=mnote_builtin,写当前用户 SQLite skill preference,不写 Hermes profile。
  • skillKind=hermes_profile,校验 canManageSkills=true
  • 拒绝普通用户修改 shared profile 的 Hermes profile skills。
  • personal profile skill toggle 只写目标 Hermes profile 的 config.yaml

错误码建议:

  • ai_profile_not_found
  • ai_profile_forbidden
  • ai_profile_readonly
  • ai_builtin_skill_preference_failed
  • hermes_skill_toggle_failed

4.4 Reasonix run

Reasonix ACP spawn / session create 需读取当前用户设置:

{
  "agentId": "reasonix",
  "memoryPolicy": {
    "enabled": false,
    "source": "user_ui_preferences"
  }
}

默认:

  • enabled=false
  • 子进程环境包含 REASONIX_MEMORY=off

开启:

  • 不设置 REASONIX_MEMORY=off,或设置为 on
  • UI 明确展示 memory 已开启

5. UI 设计

5.1 Agent selector

Hermes agent 下增加 profile 子选择:

Hermes
  我的 Hermes              personal · 可配置
  Lite                     shared · 只读

显示规则:

  • personal profile 显示“可配置”。
  • shared profile 显示“共享 / 只读”。
  • 若普通用户选择 shared profile,技能开关显示为只读。
  • 管理员选择 shared profile,技能开关可用,并显示“管理员正在修改共享 profile”。

5.2 Skills panel

三组仍保留:

  • MNote 内置技能:可折叠,可隐藏/显示,也可由普通用户按自己账号启停。
  • Hermes 技能:随当前 Hermes profile 变化;personal 可配置,shared 普通用户只读。
  • Reasonix 技能:展示可用能力;memory 是单独设置,不混入 skill toggle。

Hermes profile 切换时:

  • 必须重新加载 profile skills。
  • 必须清空旧 profile skill cache。
  • hide_builtin_skills 不随 Hermes profile 改变;它是用户 UI 偏好。
  • MNote 内置 skill enable/disable 不随 Hermes profile 改变;它是当前 MNote 用户的 SQLite policy。

5.3 Settings

设置页拆分:

  • Common:授权区域、contextRefs 默认值、内置技能显示/隐藏、内置技能启停。
  • Hermes:默认 Hermes profile、personal profile 管理、shared profile 只读/管理员管理。
  • Reasonix:默认关闭 memory;用户可开启。
  • Chat-only:只聊天配置。

6. 非目标

  • 不让普通用户直接修改 shared Hermes profile。
  • 不把 shared Hermes profile 用作沉淀个人偏好的长期人格。
  • 不在本阶段实现 Reasonix per-user HOME;只实现默认 memory off 与可选开启。
  • 不新增第二套目录授权真相;文件访问仍由 SQLite directory grants / allowedRoots 控制。
  • 不实现 PilotDeck 的完整 router、always-on 或 memory engine。

7. Checklist

Batch A - 现状冻结与风险取证

  • 复核当前 Page AI Hermes skill toggle 的真实写入路径,确认是否直接写 Hermes profile config.yaml
  • 复核当前 UI preference 中 hide_builtin、MNote 内置 skill enabled、profile skill enabled、default profile 的存储键。
  • 复核 Reasonix ACP spawn 环境,确认当前是否默认注入 memory。
  • 形成 RED 证据:普通用户修改 shared profile skill 会影响其它用户,或当前缺少服务端权限边界。
  • 验证:Rust/JS 只读审计记录在本文档或后续 checklist evidence 中。

Batch B - SQLite profile policy 合同

  • 新增或扩展 SQLite control-plane profile policyai_agent_profiles / ai_agent_profile_grants 或等价结构。
  • 初始化 shared Hermes profile:仅 lite,普通用户 canRun=truecanManageSkills=false
  • 为每个用户 provision personal Hermes profile。
  • 补 Rust 定点测试:personal owner、shared readonly、admin manage、跨用户不可管理。
  • 验证:不同用户查询 profile list 只返回自己 personal + shared lite。

Batch C - Hermes profile resolver

  • 新增服务端 agentProfileRef resolver,禁止前端提交任意 Hermes path。
  • /api/hermes/client/runsprofileId 解析真实 Hermes profile。
  • /api/hermes/client/skillsprofileId 解析真实 Hermes profile。
  • 保留旧 profile= 参数只作为兼容入口,并映射到当前用户可访问 profile。
  • 验证:旧路径兼容不允许越权访问 shared/admin profile。

Batch D - Skill toggle 权限收口

  • 修改 skill toggle API:只接受 profileId + skillName + enabled
  • 区分 mnote_builtinhermes_profile skill kind。
  • MNote 内置 skill toggle 写当前用户 SQLite preference。
  • 拒绝普通用户修改 shared profile 的 Hermes profile skills。
  • personal profile skill toggle 只写该用户 isolated profile config.yaml
  • shared profile skill toggle 仅 admin 可写。
  • 验证:Rust API 测试覆盖 ai_profile_readonly、MNote 内置 skill per-user toggle、personal profile skill success。

Batch E - MNote 内置 skill per-user policy

  • 将 MNote 内置 skill enable/disable 保存为 SQLite per-user policy。
  • UI 中 hide_builtin_skills 只影响展示,不影响 enable/disable。
  • Skills panel 标记 builtin=trueconfigurable=trueconfigScope=user_sqlite
  • 服务端 MNote tool policy 按 user_id + agentId + contextRefs + allowedRoots + mnote_builtin_skill_enabled 判断。
  • 验证:用户 A 禁用某内置 skill 不影响用户 B;禁用后对应 MNote tool 被服务端拒绝;隐藏展示不影响 enable 状态。

Batch F - Reasonix memory policy

  • 新增 per-user 设置 ai.agent.reasonix.memory_enabled,默认 false
  • Reasonix ACP spawn 默认设置 REASONIX_MEMORY=off
  • 开启 memory 后不注入 REASONIX_MEMORY=off,并在 UI 显示 memory enabled。
  • 补 JS/Rust 测试或 smoke,覆盖默认 off、用户开启、不同用户隔离 preference。
  • 验证:普通消息由 Reasonix 自己决定是否使用工具;MNote 不再强行注入 memory/context 正文。

Batch G - UI 收口

  • Agent selector 中 Hermes profile 显示 personal/shared/readonly 状态。
  • Skills panel 三组均可折叠。
  • Hermes profile 切换必须刷新 skill catalog,避免旧 profile skill 残留。
  • shared profile 的 Hermes profile skills 对普通用户展示只读开关或锁定状态。
  • MNote 内置 skills 对普通用户展示可启停状态,并标明按当前 MNote 用户保存。
  • 管理员对 shared profile 显示可管理状态,并提示影响所有用户。
  • 验证:真实浏览器截图覆盖 MNote 内置 skill per-user 可配置、personal Hermes skill 可配置、shared Hermes skill 只读、admin shared 可配置。

Batch H - 回归矩阵与文档收尾

  • 更新 Page AI 设计说明,明确 MNote 内置 skill per-user policy、personal/shared Hermes profile 与 Reasonix memory policy。
  • 更新 smokeagent 切换、MNote 内置 skill per-user toggle、Hermes profile 切换、shared readonly、personal skill toggle、Reasonix memory off/on。
  • 运行 node --check 覆盖相关 browser runtime / smoke。
  • 运行 Rust 定点测试覆盖 SQLite profile policy 与 Hermes skill toggle 权限。
  • 运行真实浏览器验证并截图。
  • 运行 git diff --check
  • 涉及代码图后运行 codegraph sync .
  • 完成后将本 checklist 移动到 done/ 或标记为 done

8. 验收口径

完成后必须满足:

  • 普通用户可以启停自己的 MNote 内置 skills,开关保存到 SQLite 并由服务端 tool policy 执行。
  • 用户 A 的 MNote 内置 skill 开关不影响用户 B。
  • 普通用户无法修改 shared lite 的 Hermes profile skills。
  • 普通用户可以修改自己的 personal Hermes profile skills。
  • MNote 内置 skill 的显示/隐藏与启停是两个不同状态:隐藏只影响 UI,启停影响服务端可调用性。
  • Hermes profile 切换后 skill catalog 正确刷新。
  • Reasonix 默认 memory off,开启 memory 是 per-user preference。
  • Page AI run payload 不再用裸 Hermes profile name 表达身份,而是经服务端解析的 agentProfileRef / profileId
  • 所有文件访问仍受 SQLite directory grants / allowedRoots 约束。