☰
Midway Agent 知识层数据契约:基于 @midwayjs/skill-midway 的官方知识快照与查询体系
2026/9/27 10:25:15 网站建设 项目流程
  • 后端
  • 微服务
  • 云原生

【免费下载链接】midway

🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载

导读

Midway 主仓中并不缺少文档、API 符号、Changelog 等知识原材料,缺的是"适合 Agent 稳定查询的数据契约"。本篇文章围绕仓库内 openspec/changes/add-midway-agent-knowledge/design.md 展开,讲解 Midway 如何将site/docs、typedoc API 数据、包元数据与版本演进信息归一化为版本化、可结构化查询的知识快照(bundle),并由@midwayjs/skill-midway包落地为统一查询 CLI 与多 AI 产品可安装的 skill。读完本文,你将掌握知识快照的四层架构、五类查询契约语义、版本解析与新鲜度策略,以及如何用midway-skill命令构建 bundle、查询文档/API/包/Changelog 并将 skill 安装到 Codex、Cursor、Trae 等 20+ 个 AI 客户端。

背景:缺口不在"有没有内容",而在"有没有数据契约"

Midway 主仓已经具备构建 Agent 知识层的核心原材料:

  • site/docs与site/versioned_docs:教程、组件、扩展、迁移文档;
  • site/versions.json与 site/docusaurus.config.js 中的 Docusaurus 当前版本配置:版本边界;
  • api-typedoc.json类结构化 API 符号与源码链接;
  • CHANGELOG.md:版本演进;
  • packages/mcp:Midway 自身的 MCP 承载能力;
  • @signalwire/docusaurus-plugin-llms-txt:面向 LLM 的文本出口。

设计文档的结论是:当前缺口不在内容本身,而在于缺少一份"适合 Agent 稳定查询的数据契约"。如果 skill、@midwayjs/skill-midway、MCP 各自去抓取站点页面并自行解析,就会产生重复抓取、重复解析、口径不一致的问题;把知识以统一契约快照的形式固化下来,才是让 Agent 稳定回答 Midway 相关问题的前提。

从仓库现状看,这一设计已经落地为@midwayjs/skill-midway包(版本 4.2.3,见 packages/skill-midway/package.json),其bin入口为midway-skill,依赖@midwayjs/bootstrap、@midwayjs/commander与@midwayjs/core,要求 Node.js >= 20。该包同时提供了"bundle 构建器 + 打包快照与查询命令 + 可安装到多种 AI 产品的 skill 工件"三样东西。

Goals / Non-Goals:设计边界

Goals(要做的事)

  • 产出一套官方、版本化、可结构化查询的知识快照;
  • 同时覆盖文档、API 符号、包维度和 changelog 语义;
  • 为 skill、@midwayjs/skill-midway、MCP 提供统一数据源,而不是各自抓站点;
  • 保持中英文信息与版本命中关系;
  • 把"最新"明确落在当前文档版本与生成时间上。

Non-Goals(明确不做的事)

  • 不在本 change 中实现向量搜索或复杂排序系统;
  • 不让 skill 文件承载大量领域正文;
  • 不把 consumer 绑定为单一命令行工具或单一 MCP 实现;
  • 不引入非官方内容源。

这段边界决定了后面所有设计:知识本体放在 bundle 里,skill 只定义 SOP(标准操作流程),查询逻辑与 transport 解耦,搜索先用简单评分而非向量检索。

四层架构:从原材料到可查询快照

设计文档将整体划分为 4 层,对应实现可见 packages/skill-midway/src/bundle/builder.ts。

1. Source Collection Layer(源收集层)

输入源包括:

  • site/docs/**;
  • site/i18n/en/docusaurus-plugin-content-docs/current/**;
  • site/versioned_docs/version-*/**;
  • site/.docusaurus/api-typedoc-default.json或对应 versionedapi-typedoc.json;
  • site/versions.json;
  • CHANGELOG.md;
  • 相关packages/*/package.json。

该层只负责收集,不负责面向 consumer 的查询逻辑。在builder.ts中对应collectDocRecords、collectApiRecords、collectChangelogRecords、collectWorkspacePackages四条收集路径。

2. Normalization Layer(归一化层)

将多源内容转换为稳定记录:DocRecord、ApiRecord、PackageRecord、ChangelogRecord、VersionRecord。完整字段定义见 packages/skill-midway/src/types.ts。

每条记录至少包含:

字段含义
id全局唯一记录 ID
kind记录类型(doc/api/changelog 等)
version所属 Midway 版本
locale语言区域(如zh-cn、en)
title标题
summary摘要
sourcePath仓库内相对路径
sourceUrl源码/文档链接

API 记录额外包含:

字段含义
packageName所属包名
symbolName符号名
symbolKind符号类别(Class/Interface/Function 等)
qualifiedName限定名(如MidwayMCPFramework)
since引入版本
deprecated是否废弃

在types.ts中可以看到实现细节:DocRecord还带有slug与headings两个用于匹配的字段;ApiRecord通过deprecated: boolean承载废弃标记;ChangelogRecord拆出了releaseVersion、releaseDate、majorVersion、summary、content与packageNames,便于按版本区间和包名过滤;PackageRecord则记录了包名、版本、描述与关键词。

builder.ts的归一化关键逻辑:

  • 当前版本通过正则从site/docusaurus.config.js的current: { label: '...' }中提取(对应extractCurrentVersionFromConfig),历史版本读取site/versions.json,最终版本列表为[currentVersion, ...historicalVersions]。当前仓库中site/versions.json的内容为["3.0.0", "2.0.0", "1.0.0"],而 site/docusaurus.config.js 中 current 的 label 为4.0.0,因此快照会覆盖 4.0.0 / 3.0.0 / 2.0.0 / 1.0.0 四个版本;
  • API 数据仅在当前版本收集:const apiSupported = version === currentVersion;,历史版本不产出api.json;
  • 文档按 locale 根目录解析:当前版本取site/docs(zh-cn)与site/i18n/en/docusaurus-plugin-content-docs/current(en),历史版本取site/versioned_docs/version-<v>与对应的 i18n 目录,不存在的目录自动跳过。

文档归一化(packages/skill-midway/src/bundle/docs.ts)会递归扫描docsRoot下所有.md/.mdx文件,用slug(去掉扩展名的相对路径)作为主键,并通过一个零依赖的 front matter 解析器(packages/skill-midway/src/bundle/markdown.ts)提取title、首个非标题段作为summary、全部#标题作为headings;标题缺失时回退到文件名。

API 归一化(packages/skill-midway/src/bundle/typedoc.ts)解析 typedoc JSON 树,维护一张ReflectionKind数值到标签的映射表(如 128=Class、256=Interface、2048=Method),并排除 Project/Module/签名/参数等噪声节点;qualifiedName由祖先链拼接而成,废弃标记同时识别flags.isDeprecated与@deprecated修饰标签,源码链接则优先采用 typedoc 的sources[0](fileName + line)。

Changelog 归一化(packages/skill-midway/src/bundle/changelog.ts)用正则^##\s+v?([^\s]+)\s+\(([^)]+)\)\s*$切分发布区块,并从正文反引号代码片段中抽取涉及的包名列表(去@midwayjs/前缀)。

3. Bundle Distribution Layer(快照分发层)

知识快照输出为 transport-neutral bundle,建议目录结构如下:

midway-skill/ manifest.json versions/ 4.0.0/ docs.json api.json packages.json changelog.json 3.0.0/ docs.json api.json packages.json changelog.json

manifest.json提供:当前版本、历史版本列表、生成时间、支持的 locale、每个 bundle 文件的路径与摘要。在实现中,KnowledgeManifest(types.ts)包含schemaVersion: 1、generatedAt(ISO 时间戳)、currentVersion、repoUrl与versions: VersionBundleManifest[];每个版本的VersionBundleManifest还记录了docsFile/apiFile/packagesFile/changelogFile的相对路径、各文件记录条数,以及capabilities: { docs, api, changelog }能力开关。这正是设计文档中"manifest 显式记录每个 version 的 docs/api 可用性"这一风险缓解措施的实现。

buildKnowledgeBundle(builder.ts)会先清空输出目录,再为每个版本写四个 JSON 文件(历史版本跳过api.json),最后写出manifest.json。

4. Consumer Layer(消费层)

官方只冻结查询契约,不冻结唯一 transport。典型 consumer:

  • 官方 skill;
  • @midwayjs/skill-midway;
  • 基于packages/mcp的参考 knowledge server;
  • 站点调试工具页。

也就是说,无论 Agent 最终以何种形态接入(本地 CLI、MCP server、站点页面),其背后查询的都是同一份 bundle 与同一套查询函数。

Query Contract:五类查询语义

consumer 侧必须至少支持以下查询语义,全部实现在 packages/skill-midway/src/lookup/query.ts:

1.resolveVersion(target)

  • 输入:current、显式 semver、latest;
  • 输出:resolvedVersion、matchType。

实现中的matchType有三种取值:alias(current/latest别名命中当前版本)、exact(显式版本精确命中)、fallback(未命中时回退)。回退策略为:提取请求版本的主版本号,在同 major 下挑选最高的已发布快照;若同 major 也没有,则整体回退到currentVersion。比较时使用compareSemverish处理v前缀与 prerelease 后缀(见query.ts中parseSemverish)。

2.lookupDocs({ query, version, locale })

按主题、标题、slug、标题层级匹配文档。实现中按title、slug、summary、headings四个字段打分,可用--locale过滤(如zh-cn/en),默认返回前 10 条。

3.lookupApi({ symbol, packageName?, version })

按导出名、限定名、包名查 API。实现中会对symbolName、qualifiedName、packageName、summary打分,支持--package精确过滤包名;若目标版本capabilities.api === false,直接返回空数组——这呼应了 README 中"历史版本的 API 查询不做保证"的版本行为说明。

4.lookupPackages({ query, version })

按包名、关键词、分类查 Midway 包。实现对name、description、keywords打分,包数据来自packages、packages-serverless、packages-resource三个工作区下所有含package.json的目录(见collectWorkspacePackages)。

5.lookupChangelog({ fromVersion, toVersion?, packageName? })

返回变更条目和关联版本范围。实现支持--package(自动兼容带/不带@midwayjs/前缀)与--from-version/--to-version区间过滤,结果按版本号降序,默认取前 10 条。

所有查询返回都必须带:resolvedVersion、sourceKind、sourcePath、sourceUrl、confidence或matchType。底层打分算法(computeScore)为:字段精确等于查询词得 100 分、前缀命中得 50 分、包含命中得 10 分,取各字段最高分排序后截断——这是设计文档 Non-Goals 中"不做向量检索/复杂排序"的直接落地。

CLI 层通过@midwayjs/commander注册了全部命令(见 packages/skill-midway/src/cli/app.ts 的preloadModules列表),每个查询命令以结构化 JSON 输出到 stdout,方便 Agent 与脚本消费。例如lookup-docs命令(packages/skill-midway/src/cli/commands/lookup-docs.command.ts)会一并返回bundleRoot、query、requestedVersion、resolvedVersion、matchType、capabilities、count与records字段。

官方 Skill 设计:只定义 SOP,不复制知识正文

官方 skill 文件位于 packages/skill-midway/skills/midway/SKILL.md,其设计原则是"skill 只定义 SOP,不直接复制知识正文",因为 skill 的职责是强制 Agent 查询官方源,而不是变成另一本维护成本极高的手册。

最小要求:

  1. 触发范围:Midway 框架、包、装饰器、配置、生命周期、命令行工具、MCP、部署、迁移相关问题;
  2. 默认流程:先解析版本 → 再查 knowledge bundle → 命中不足时回退到官方文档页面或源码位置;
  3. 输出约束:必须说明命中的 Midway 版本;必须优先引用官方来源;推断内容要显式标注是推断。

SKILL.md的具体流程(Workflow)为:先用resolve-version <version>解析用户请求的版本(未指定则用current);再按问题类型调用lookup-docs --query "<topic>"、lookup-api --symbol "<symbol>"、lookup-packages --query "<package or feature>"、lookup-changelog --package "<package>";最后在回答中引用 bundle 解析出的版本、命中结果与源码路径。

SKILL.md的 Rules 明确了 Agent 的行为边界:优先 bundle 结果而非记忆;历史主版本只保证 docs 与 changelog;当resolve-version报告api: false时不得断言历史 API 细节;结果为空时如实说明"bundle 中没有匹配"而不是编造;已知时优先使用@midwayjs/scope 的包名。Output 部分则强制回答必须说明解析出的 Midway 版本、概括命中的记录,并尽量保留 bundle 记录中的链接与源码路径。

多目标安装与更新:一个 skill,多种 AI 产品

midway-skill install与midway-skill update命令将内置 skill 工件安装到当前项目,目标适配层实现在 packages/skill-midway/src/targets/registry.ts,当前支持 20+ 个目标:

amazon-q antigravity auggie claude cline codebuddy codex continue costrict crush cursor factory gemini github-copilot iflow kilocode kiro opencode pi qoder qwen roocode trae windsurf

不同目标的产物格式不同:Codex 与 Trae 安装为SKILL.md(含资源文件),Cursor/iflow 安装为/opsx-midway斜杠命令,Gemini/Qwen 安装为 TOML,Continue 安装为.continue/prompts,GitHub Copilot 安装为.github/prompts,其余多为.md描述文件。skill 内容统一从skills/midway/SKILL.md读取并解析 front matter(packages/skill-midway/src/targets/content.ts),各 adapter 负责把同一份内容渲染成对应产品要求的格式。

安装逻辑(packages/skill-midway/src/cli/install.ts)要点:

  • 默认项目级安装,写入当前工作目录(可用--dest覆盖);
  • --target支持逗号分隔多目标,all表示全部安装;
  • 目标已存在且未指定overwrite时抛出错误,update命令本质上是带overwrite: true的安装;
  • 非交互终端(无 TTY)下必须显式传--target,否则报错。

这种"项目作用域安装"的方式保证了已安装 skill 的版本与项目依赖的@midwayjs/skill-midway版本保持一致,避免 Agent 用过期记忆回答新版问题。

版本策略(Versioning Strategy)

  • current对应站点当前文档版本标签(本仓库为4.0.0);
  • 历史版本来自site/versions.json(本仓库为3.0.0、2.0.0、1.0.0);
  • 查询显式版本时优先 exact match;
  • 无 exact match 时可回退到"同 major 下最近的已发布快照",并向 consumer 暴露fallback=true(实现中即matchType: 'fallback')。

配套的版本行为(README 与 builder 双重印证):当前主版本能力为docs + api + changelog;历史主版本只有docs + changelog;历史 API 查询不做保证,能力缺失时返回空结果。因此任何版本敏感的问题都应先跑resolve-version,让调用方看清结果是精确命中还是主版本回退。

新鲜度策略(Freshness Strategy)

知识快照的生成应与文档/API 构建绑定,而不是独立手工维护。最低要求:

  • 文档构建时生成当前版本 bundle;
  • 版本化文档构建时保留历史 bundle;
  • 生成产物记录generatedAt(KnowledgeManifest.generatedAt已实现);
  • CI 对以下情况给出失败信号:
    • 当前文档存在但当前 bundle 缺失;
    • 当前 API typedoc 存在但 API bundle 缺失;
    • 版本清单与 bundle 目录不一致。

build命令(packages/skill-midway/src/cli/commands/build.command.ts)默认输出到site/.midway-skill,并同步到包内发布目录packages/skill-midway/bundle(随 npm 包一起发布),也支持--repo-root、--site-root、--output、--package-bundle覆盖路径。

关键决策(Decisions)

决策原因
先做 bundle,再做 transport@midwayjs/skill-midway、MCP、skill 共享同一份数据契约,避免重复抓取和重复解析
以 docs + typedoc 为双主源Midway 的"怎么用"主要在 docs,"能调什么"主要在 typedoc,两者缺一不可
latest不直接指 npm registry对 Agent 来说,最可信的"最新"应是当前站点发布并完成 bundle 生成的版本,而不是尚未同步文档的包版本
skill 与数据分离skill 的职责是强制 Agent 查询官方源,而不是变成另一本维护成本极高的手册

风险与权衡(Risks / Trade-offs)

  • 风险:docs 与 typedoc 的版本边界不完全一致Mitigation:manifest 中显式记录每个 version 的 docs/api 可用性(capabilities字段正是为此设计)。
  • 风险:历史版本文档结构差异较大,归一化复杂Mitigation:先定义最小公共字段,保留rawSourcePath作为兜底(实现中每条记录均带sourcePath/sourceUrl指向原始文件)。
  • 风险:consumer 直接依赖站点内部生成文件路径,导致后续改动成本高Mitigation:consumer 只依赖 manifest 和 bundle contract,不依赖 Docusaurus 内部目录细节(loadManifest/loadVersionBundle只按 manifest 中的相对路径读取)。

迁移计划(Migration Plan)

  1. 在site构建链路中加入 knowledge bundle 生成;
  2. 为当前版本与历史版本产出统一 manifest;
  3. 增加官方 skill 文件(已完成,见 packages/skill-midway/skills/midway/SKILL.md);
  4. 由@midwayjs/skill-midway与 MCP 等 consumer 消费该 bundle,而不是自行爬站点。

实践:在仓库中构建与查询知识快照

在 Midway 主仓环境下,可直接通过 pnpm 使用@midwayjs/skill-midway的命令:

# 查看帮助 pnpm exec midway-skill --help # 构建知识快照(默认写入 site/.midway-skill,并同步到包内 bundle 目录) pnpm exec midway-skill build # 自定义路径构建 pnpm exec midway-skill build \ --repo-root /path/to/midway \ --site-root /path/to/midway/site \ --output /path/to/output # 先解析版本 pnpm exec midway-skill resolve-version 3.20.12 # 查询文档 pnpm exec midway-skill lookup-docs --query "mcp" pnpm exec midway-skill lookup-docs --query "configuration" --locale en # 查询 API 符号 pnpm exec midway-skill lookup-api --symbol "Configuration" pnpm exec midway-skill lookup-api --symbol "MidwayMCPFramework" --package "@midwayjs/mcp" # 查询包元数据 pnpm exec midway-skill lookup-packages --query "mcp" # 查询 changelog pnpm exec midway-skill lookup-changelog --package "@midwayjs/mcp" pnpm exec midway-skill lookup-changelog --from-version 4.0.0 --to-version 4.0.1 # 安装 skill 到 AI 产品 pnpm exec midway-skill install --target codex pnpm exec midway-skill install --target cursor pnpm exec midway-skill install --target trae pnpm exec midway-skill install --target all pnpm exec midway-skill install --target codex --dest /path/to/project # 覆盖更新已安装的 skill pnpm exec midway-skill update --target codex pnpm exec midway-skill update --target all

注意:当包内已打包 bundle 快照时,查询命令优先读取包内 bundle;在 Midway 源码仓库中,也可以用--bundle-root显式指向site/.midway-skill。所有 lookup 命令都在 stdout 输出结构化 JSON,便于 Agent 与脚本直接消费。

质量验证:测试用例如何印证契约

packages/skill-midway/test/index.test.ts 用 fixture 完整验证了设计文档的每一条契约:

  • 构建契约:断言manifest.json、当前版本docs.json/api.json/packages.json/changelog.json存在,历史版本(3.0.0)api.json不存在,且capabilities分别为{ docs: true, api: true, changelog: true }与{ docs: true, api: false, changelog: true };
  • 版本解析:resolveVersion(manifest, 'latest')返回matchType: 'alias'且解析到当前版本;resolveVersion(manifest, '3.20.12')回退到3.0.0且matchType: 'fallback';
  • 查询行为:lookupDocs支持 locale 过滤并命中标题;lookupApi在当前版本命中Configuration、在历史版本返回空数组;lookupPackages按包名命中;lookupChangelog按包名过滤返回对应 release;
  • CLI 行为:build命令产出 bundle 并同步 package-bundle;resolve-version命令输出 JSON 载荷;lookup-docs/lookup-api命令返回带resolvedVersion/capabilities/count的结构化结果;install/update命令验证了 CodexSKILL.md、Cursor 斜杠命令、TraeSKILL.md的写入、覆盖与 TTY 交互保护。

Open Questions:仍在演进中的问题

设计文档保留了三个开放问题,也体现了该体系的边界意识:

  • 官方 skill 最终是保留在主仓,还是镜像发布到独立 skill 仓库?
  • bundle 是直接随站点静态文件发布,还是同步发布一个轻量 npm 数据包(首选名@midwayjs/skill-midway)?——目前仓库中@midwayjs/skill-midway已作为 npm 包形态存在,并将 bundle 随包发布;
  • lookupDocs是否需要在第一阶段支持全文倒排索引,还是先以标题/slug/heading 命中为主?——当前实现以标题/slug/heading/摘要的加权打分为主,与 Non-Goals 中的"不实现向量搜索"保持一致。

小结

从设计文档到落地实现,Midway Agent 知识层的核心思路可以概括为:先固化数据契约,再放开 transport。@midwayjs/skill-midway用四层架构把 docs、typedoc、packages、changelog 归一为版本化 JSON 快照,用manifest.json统一描述版本边界与能力开关,用五个查询函数冻结查询语义,再用一个只定义 SOP 的SKILL.md约束 Agent 优先查官方源。对希望为自家框架构建 Agent 知识体系的开发者来说,这份 design + 实现组合本身就是一个可复用的参考范式:内容不重复维护、版本不靠猜、查询不靠爬。

  • 后端
  • 微服务
  • 云原生

【免费下载链接】midway

🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载

相关推荐

上一篇:百度网盘解析工具终极指南:3分钟实现10倍下载加速
下一篇:告别龟速下载:用Python解析工具解锁百度网盘10倍下载速度

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询