Files
memind/docs/architecture/page-template-skill-design.md
T
john fde6503bdf
Memind CI / Test, build, and release guards (push) Has been cancelled
feat(mindspace): add SEO/GEO delivery, page template catalog, and admin hooks
Enable optional SEO/GEO injection and discovery routes for confirmed public pages while keeping private pages noindex. Add premium page template skills, portal catalog API, template shop UI, and Baidu push gated by memind_adm config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 08:06:12 +08:00

18 KiB
Raw Blame History

页面模板 Skill 设计(Agent 可调用 + 授权勾选 + 二期购买)

日期: 2026-08-04

状态: 已实现(Phase 1 + 余额购买) — 见 page-template-catalog.mjs、三个 page-template-* skill、Portal/Admin API。

1. 背景与目标

当前 H5 页面由 Goose Agent 按 static-page-publish 规范从零生成 HTML,平台只提供约束(cover 元数据、CSP、页脚标记等),没有可复用的 HTML 骨架库。导致:

  • 样式与结构不稳定,同类页面差异大
  • 易漏写 mindspace-cover、平台页脚、Page Data 脚本引用
  • 用户无法选择「旅游 Hero / 商品促销 / 问卷壳」等固定视觉风格

目标:

  1. 提供一套平台维护的 HTML 模板,Agent 通过 skill 读取并填充后落盘 public/*.html
  2. 不影响现有 static-page-publishwrite_file → finish guard 主链路
  3. 一期:管理员在 memind_adm 授权,用户在 H5 聊天勾选模板 skill
  4. 二期:用户可在模板商城购买,支付成功后自动写 skill grant

2. 核心结论

层级 负责方 说明
HTML 骨架 Memind 平台 skills/page-template-* 预置合规 HTML + 占位符
文案 / 章节内容 Goose + LLM(常见 DeepSeek 填占位符,不发明骨架
授权(谁能用) h5_user_skill_grants 与现有 skill 体系一致
使用(这次用哪个) H5 聊天 skill 芯片 / 模板选择器 注入 templateId 到 prompt
发布与守卫 不变 finish guard、cover 检查、Page Data bind

一句话:

模板是可选 skill 资产;未授权 = 行为与今天完全一致;授权且勾选 = Agent 读模板再 write_file。

3. 对现有链路的影响(硬约束)

3.1 不变的部分

  • static-page-publish 仍是默认发布 skillcreator 角色或 static_publish 能力)
  • finish guard、mindspace-cover 检查、Page Data finish sync、sandbox MCP 路径规则
  • syncSkillsToWorkspace 只同步已授权 skill;未授权模板不会出现在工作区
  • 意图路由:coercePageGenerationSkill / page-data-collect 优先级不变

3.2 增量部分

  • 新增若干 page-template-* platform skill(默认 关闭
  • 可选:page-templates 聚合 skill(目录索引 + 共用 SKILL.md),或每个模板独立 skill 便于单独定价
  • CHAT_SKILL_DEFINITIONS 增加模板入口(仅 grantedSkills 包含时可见)
  • Agent 工作流多一步:read_file 模板 → 替换占位符 → write_file

3.3 禁止事项

  • 禁止把 static-page-publish 改为「必须选模板」
  • 禁止模板 skill 绕过 page-data-collect 的 bind / policy 流程
  • 禁止在模板 HTML 内写 localStorage / 外链 <script src="https://...">
  • Page Data 类模板必须预置 /assets/page-data-client.js 引用位,Agent 只填 dataset 相关占位符

4. 目录结构

4.1 推荐:一模板一 skill(便于授权与定价)

skills/
├── page-template-travel/
│   ├── SKILL.md
│   ├── skill.yaml
│   └── templates/
│       └── travel-hero.html
├── page-template-campaign/
│   ├── SKILL.md
│   ├── skill.yaml
│   └── templates/
│       └── campaign-cta.html
├── page-template-report/
│   ├── SKILL.md
│   ├── skill.yaml
│   └── templates/
│       └── report-editorial.html
└── page-template-survey/
    ├── SKILL.md
    ├── skill.yaml
    └── templates/
        ├── survey-basic.html      # 前台问卷壳
        └── survey-admin-read.html # 后台只读壳(password read

同步后位于用户工作区:

MindSpace/<userId>/.agents/skills/page-template-travel/templates/travel-hero.html

4.2 可选:聚合 skill(一期快速试点)

skills/page-templates/
├── SKILL.md           # 索引:templateId → 文件路径 + 适用场景
├── skill.yaml
└── templates/
    ├── travel-hero.html
    ├── campaign-cta.html
    └── ...

权衡:

方案 优点 缺点
一模板一 skill 单独 grant/定价;商城 SKU 一一对应 skill 数量多
聚合 skill 实现快,一个 grant 全开 无法按模板单独售卖

建议: 一期用聚合 page-templates 试点;二期拆成 page-template-* 便于商城。


5. 模板文件规范

5.1 占位符约定

使用 Mustache 风格,Agent 替换后不得残留 {{

<title>{{PAGE_TITLE}}</title>
<meta name="description" content="{{PAGE_DESCRIPTION}}">
<meta name="mindspace-cover" content='{{MINDSPACE_COVER_JSON}}'>
<h1>{{HERO_HEADLINE}}</h1>
<div class="content">{{MAIN_CONTENT_HTML}}</div>
占位符 必填 说明
PAGE_TITLE 浏览器标题
PAGE_DESCRIPTION description + cover subtitle 来源
MINDSPACE_COVER_JSON 合法 JSON 字符串(tag/accent/cover 等)
HERO_HEADLINE 视模板 首屏标题
MAIN_CONTENT_HTML Agent 生成的正文 HTML 片段(已 escape 或由 Agent 保证安全)
ACCENT / ACCENT2 推荐 与 CSS 主色一致

Page Data 问卷模板额外占位符:

占位符 说明
DATASET_ID 注册后的 dataset id
FORM_FIELDS_HTML 表单字段块
ADMIN_PAGE_FILENAME 后台页相对路径 hint

5.2 模板自检清单(入库前)

  • 完整 <!DOCTYPE html>lang="zh-CN"viewport
  • <meta name="mindspace-cover"> 占位符或示例结构
  • 页脚含 data-mindspace-page-tag="platform-brand"TKMind · 智趣
  • 无 CDN scriptChart 等用 /assets/chart.umd.min.js 或相对路径
  • 问卷类含 <script src="/assets/page-data-client.js">
  • 运行 npm run check:mindspace-cover 对填充样例通过

5.3 SKILL.md 工作流摘要(Agent 必读)

## 何时使用

- 用户在本轮对话中**明确选择**了「旅游模板 / 促销模板 / …」
- 或 prompt 前缀含 `templateId=travel-hero`

## 工作流

1. 确认用户已授权本 skillload_skill 成功)
2. read_file → `.agents/skills/page-template-travel/templates/travel-hero.html`
3. 根据用户需求生成文案与 MAIN_CONTENT_HTML
4. 替换全部占位符,自检无残留 `{{`
5. write_file → public/<slug>.html
6. 若需 Page Data:仍走 page-data-collect(建表 → register → bind),不得跳过
7. 按 static-page-publish 回复 Markdown 链接

## 何时不用

- 用户未选模板 → 继续 static-page-publish 从零写 HTML
- 用户要求完全自定义版式且与模板冲突 → 从零写,说明原因

6. skill.yaml 示例

# skills/page-template-travel/skill.yaml
name: page-template-travel
version: 1.0.0
label: 旅游 Hero 模板
description: 深色沉浸 + Hero 图 + 卡片区块,适用于旅游/美食/城市攻略
catalog:
  previewImage: /assets/template-previews/travel-hero.png
  priceCents: 990          # 二期商城展示;一期忽略
  category: page-template
trigger:
  keywords:
    - 旅游模板
    - 攻略模板
    - travel-hero
router:
  promptKey: page-template-travel
  priority: 25
requires:
  - static-page-publish    # 文档约定;运行时仍靠 grant 控制
executors:
  - goose

skills-registry.mjsparseSkillManifest 已支持扩展字段;catalog / requires 为二期预留,一期 parser 可忽略未知键。


7. 授权模型(复用现有 skill grant

7.1 现有表(无需改 schema — 一期)

-- 已有:h5_user_skill_grants
-- subject_type: 'role' | 'user'
-- subject_id:   'user' | <userId>
-- skill_name:   如 'page-templates' 或 'page-template-travel'
-- enabled:      0 | 1

解析链(已实现):

listSkillGrants('role','user') + listSkillGrants('user', userId)
  → resolveSkillMap()
  → grantedSkillNames()
  → syncSkillsToWorkspace()   // 仅 enabled skill 复制到 .agents/skills/
  → filterChatSkills()        // H5 聊天入口过滤
  → resolveSkillPrompt()      // 意图路由不注入未授权 skill

7.2 默认策略(一期)

skills-registry.mjsDEFAULT_USER_SKILLS 中:

'page-templates': false,           // 聚合 skill,试点
'page-template-travel': false,     // 拆分后逐项默认关
'page-template-campaign': false,
'page-template-survey': false,

creator 预设可选开启:

creator: {
  ...DEFAULT_USER_SKILLS,
  'page-templates': true,
},

7.3 memind_adm 操作(一期)

复用已有 Admin APIMemind admin-routes.mjs):

方法 路径 用途
GET /admin-api/skills/catalog 列出含新 template skill
GET /admin-api/users/:userId/skills 查看用户有效 skill
PUT /admin-api/users/:userId/skills { "skills": { "page-templates": true } }
PUT /admin-api/skills/role/user 角色默认批量开启

setUserSkills 成功后已调用 syncUserSkillsForUser下次会话工作区即有模板文件。


8. H5 聊天勾选(复用 skill 芯片)

8.1 扩展 CHAT_SKILL_DEFINITIONS

chat-skills.mjs 增加(示例):

{
  id: 'page-template-travel',
  label: '旅游模板',
  icon: 'page',
  skillName: 'page-template-travel',
  requiresSkill: 'page-template-travel',
  requiresPublish: true,
  promptKey: 'page-template-travel',
},

filterChatSkills 逻辑已满足:

  • requiresSkill → 必须在 grantedSkills
  • requiresPublish → 需 canPublish 或已 grant page-data-collect(页面类统一规则)

8.2 Prompt 前缀

buildChatSkillPrompt 增加:

case 'page-template-travel':
  return (
    '请使用 page-template-travel 技能:先 load_skill,再 read_file 读取 templates/travel-hero.html' +
    '按模板占位符填充内容(templateId=travel-hero),write_file 到 public/页面.html' +
    '并遵守 static-page-publish 的 mindspace-cover 与链接格式。页面主题:'
  );

用户点击芯片 → pendingSkillRef → 发送带前缀的消息 → Agent 走模板流程。

8.3 二期:独立模板选择器(可选 UI)

在「生成页面」芯片点击后展开二级面板:

  • 展示 GET /api/mindspace/v1/template-catalog 返回的已购模板列表
  • 单选 templateId → 合并进 prompt

一期可仅用聊天芯片,不做二级 UI。


9. Agent 执行时序

sequenceDiagram
  participant U as 用户
  participant H5 as H5 Chat
  participant P as Portal
  participant G as Goose
  participant WS as 用户工作区

  U->>H5: 点击「旅游模板」+ 输入主题
  H5->>P: POST /agent/run (含 skill 前缀)
  P->>P: grantedSkills 含 page-template-travel?
  P->>G: 会话 constraints + 用户消息
  G->>G: load_skill(page-template-travel)
  G->>WS: read_file templates/travel-hero.html
  G->>G: LLM 生成文案 + 填占位符
  G->>WS: write_file public/xxx.html
  G->>P: Finish + 链接
  P->>P: finish guard / cover 检查
  P->>U: 可点击公网链接

10. 二期:购买与商城(新增)

10.1 新增表(建议)

CREATE TABLE IF NOT EXISTS h5_template_catalog (
  skill_name       VARCHAR(64) PRIMARY KEY COMMENT '与 platform skill name 一致',
  label            VARCHAR(128) NOT NULL,
  description      TEXT,
  preview_url      VARCHAR(512) NULL,
  price_cents      INT NOT NULL DEFAULT 0,
  currency         VARCHAR(8) NOT NULL DEFAULT 'CNY',
  billing_mode     ENUM('free','one_time','subscription') NOT NULL DEFAULT 'one_time',
  status           ENUM('draft','active','archived') NOT NULL DEFAULT 'draft',
  sort_order       INT NOT NULL DEFAULT 0,
  created_at       BIGINT NOT NULL,
  updated_at       BIGINT NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS h5_template_purchases (
  id               CHAR(36) PRIMARY KEY,
  user_id          CHAR(36) NOT NULL,
  skill_name       VARCHAR(64) NOT NULL,
  order_id         VARCHAR(64) NULL COMMENT '关联支付单',
  source           ENUM('purchase','admin_grant','promo') NOT NULL,
  purchased_at     BIGINT NOT NULL,
  expires_at       BIGINT NULL COMMENT '订阅型模板到期;NULL=永久',
  UNIQUE KEY uq_user_template (user_id, skill_name),
  KEY idx_template_user (user_id),
  CONSTRAINT fk_template_purchase_user FOREIGN KEY (user_id) REFERENCES h5_users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

与 skill grant 关系:

  • 购买成功 / 管理员赠送 → 写 h5_template_purchases + h5_user_skill_grants(enabled=1)
  • 退款 / 到期 → enabled=0 + 可选删除工作区 .agents/skills/page-template-*
  • resolveUserSkillMap 可扩展:有效 purchase 视为 grant(即使无 user override 行)

10.2 Portal 用户 API(草案)

方法 路径 说明
GET /api/mindspace/v1/template-catalog 商城列表(含是否已购)
GET /api/mindspace/v1/template-catalog/mine 当前用户已购/已授权模板
POST /api/mindspace/v1/template-catalog/:skillName/checkout 创建支付单(对接现有 billing
POST /api/mindspace/v1/template-catalog/:skillName/activate 支付回调内部:写 purchase + grant

响应示例:

{
  "items": [
    {
      "skillName": "page-template-travel",
      "label": "旅游 Hero 模板",
      "description": "深色沉浸 + Hero 图",
      "previewUrl": "https://m.tkmind.cn/assets/template-previews/travel-hero.png",
      "priceCents": 990,
      "owned": true,
      "chatSkillId": "page-template-travel"
    }
  ]
}

10.3 memind_adm 商城管理(UI 边界)

AGENTS.md商城配置页在 memind_adm5174Memind 本仓只实现 API 与 skill 资产。

memind_adm 需新增:

  • 模板 SKU 配置(映射 h5_template_catalog
  • 用户已购模板查询
  • 手动赠送 / 撤销(调 Memind admin API 或直接写 grant

10.4 支付回调伪代码

async function onTemplatePaymentSuccess({ userId, skillName, orderId }) {
  await pool.query(
    `INSERT INTO h5_template_purchases (id, user_id, skill_name, order_id, source, purchased_at)
     VALUES (?, ?, ?, ?, 'purchase', ?)
     ON DUPLICATE KEY UPDATE order_id = VALUES(order_id), purchased_at = VALUES(purchased_at)`,
    [uuid(), userId, skillName, orderId, Date.now()],
  );
  await userAuth.setUserSkills(userId, { [skillName]: true });
}

11. 代码改动清单(实施顺序)

Phase 1 — 试点(无购买)

# 仓库 文件 / 模块 改动
1 Memind skills/page-templates/ 新增 SKILL.md + 23 个 HTML 模板
2 Memind skills-registry.mjs DEFAULT_USER_SKILLS['page-templates']=false
3 Memind chat-skills.mjs CHAT_SKILL_DEFINITIONS + buildChatSkillPrompt
4 Memind chat-skills.test.mjs filterChatSkills / prompt 单测
5 memind_adm 用户技能页 勾选 page-templates(若尚未暴露 catalog 新项,刷新 catalog 即可)
6 Memind scripts/verify-page-template-samples.mjs 可选:占位符填充样例 + cover 检查

验收:

  1. 未授权用户:聊天无模板芯片,Agent 行为与现网一致
  2. 管理员授权后:出现「页面模板」芯片,生成页使用模板骨架且 cover 检查通过
  3. npm run verify:mindspace-publish-guards 仍通过

Phase 2 — 商城与购买

# 模块 改动
1 schema.sql + migration h5_template_catalog / h5_template_purchases
2 Portal routes template-catalog API + checkout
3 billing 集成 模板 SKU 入账
4 memind_adm 商城 UI + 赠送
5 拆分 skill page-templatespage-template-* 独立定价

12. 测试计划

场景 预期
无 grant 无芯片;自然语言「做旅游页」仍走 static-page-publish
有 grant,未点芯片 可走模板或从零(SKILL 约定优先响应用户明确指定)
有 grant,点芯片 read_file 模板 → write_file;链接可访问
Page Data 模板 仍完成 bindverify:page-data 通过
撤销 grant 下次 sync 删除 .agents/skills/page-template-*
购买回调 purchase 行 + grant;芯片即时可见(需 refresh capabilities

13. 风险与缓解

风险 缓解
Agent 占位符漏替换 SKILL 强调自检;verify 脚本 grep {{
模板与 Page Data 流程脱节 survey 模板仅提供壳;bind 步骤写入 SKILL 强制清单
skill 过多难维护 一期聚合;二期按销量拆包
购买与 grant 不一致 purchase 表为 source of truth;定时 reconcile job

14. 相关文档与代码

主题 位置
静态页发布规范 skills/static-page-publish/SKILL.md
Skill 同步 skills-registry.mjssyncSkillsToWorkspace
Skill grant user-auth.mjsresolveUserSkillMap
聊天 skill 芯片 chat-skills.mjsCHAT_SKILL_DEFINITIONS
Admin skill API admin-routes.mjs /skills/*
Page Data 交付 docs/regression-guards/page-data-delivery-contract.md
管理后台 UI 边界 AGENTS.md → memind_adm 5174

15. 开放问题(产品确认)

  1. 一期聚合 skill 还是直接按模板拆 skill
  2. 模板定价:买断 vs 订阅 vs 套餐捆绑?
  3. 是否在「生成页面」芯片下做二级模板预览 UI,还是仅聊天芯片?
  4. creator 角色是否默认赠送全部模板?

确认后可按 Phase 1 清单开分支实现。