Files
homeagent-sdk/tools/apidoc
JianFeeeee 255d6479ad feat(docs): 换品牌图标 + 补备案号 + 给 agent 的直读入口
三件事,都是「站点上线后看出来的」问题。

## ① 图标用的是 Material 默认,不是我们的

站上 favicon 是 mkdocs-material 自带的那张(`assets/images/favicon.png`),
与主站 introduce 不一致。改为引入主站同一份 logo:

- `docs/assets/logo.svg` —— 原样(浅色底,适合 favicon)
- `docs/assets/logo-mark.svg` —— 去掉底色矩形(否则在靛蓝页头上是个白方块)

`theme.favicon` / `theme.logo` 分别指向它们。实测子页面路径也正确
(mkdocs 生成 `../../assets/logo.svg`,不是错误的相对路径)。

## ② 缺备案号

`introduce` 底部有 ICP + 公安备案,文档站没有。Material 的 footer 只渲染
`config.copyright` 一个字符串,塞不进「两条带链接的备案」——所以覆盖了
`overrides/partials/footer.html`(`theme.custom_dir`),并顺带把许可也写进底部,
读者在任何一页都能看到,不必翻到首页。

## ③ 没有给 agent 的入口

站点是给人看的(HTML + 主题 + JS 搜索),但越来越多读者是 agent。让它们爬
HTML 既浪费 token(样板占大头)又容易漏内容。

新增 `tools/apidoc/gensite/agent.go`,随构建产出:

| 路径 | 内容 |
|---|---|
| `/llms.txt` | 站点目录:每页一行,带 URL 与一句话说明(4.3KB)|
| `/llms-full.txt` | 全部文档正文拼成一份,可一次读完(115KB)|
| `/<page>.md` | 每个页面的 Markdown 原文,含生成的 API 页(text/markdown)|

沿用 llms.txt 社区约定:`llms.txt` 读目录、`llms-full.txt` 一次读全。

**一个必须处理的坑**:mkdocs 只把 `.md` **渲染**成 HTML,不会把 Markdown
放进产物目录 —— 那样 `llms.txt` 里的链接会全部 404。所以 `build.sh` 增加了
第 4 步 `copy_agent_files`,在构建后把 23 个 Markdown 复制进 `site_build/`。

`docs/llms-full.txt` 已 gitignore:它是派生件,改任何一页都会整份重写,
进版本库只产生噪声(`llms.txt` 索引小且稳定,仍提交)。

验证:`mkdocs build --strict` 零告警;favicon/logo 可取(200,naturalWidth=400);
三页底部均含两个备案号;4 个 agent 入口均可访问且 content-type 正确。
2026-09-24 13:27:58 +08:00
..

插件 SDK 文档站

用 MkDocs Material 构建的 SDK 文档站。API 参考不是手写的 —— 它从 sdk/*.go 的源码注释生成,因为手抄必然与代码漂移。

目录结构

mkdocs.yml                    站点配置(导航、主题、中文检索)
docs/
├── index.md               ┐
├── versions.md            │
├── guide/*.md             ├─ 手写:指南、边界说明、版本
├── api/index.md           │
├── javascripts/           │
│   └── api-search.js      │  自建 API 检索(按名称/描述/签名)
├── stylesheets/extra.css  ┘
├── api/*.md               ┐ 生成物 —— 勿手改
├── examples/index.md      │ (build 时覆盖)
└── assets/api-index.json  ┘
tools/apidoc/                 生成器(本仓 Go 代码,零外部依赖)
├── extract.go                从源码提取符号、注释、分层
├── tiers.go                  应用能力分层(public / builtin / bridge)
├── tiers.json                **能力边界的事实源**(每条附源码依据)
├── gensite/main.go           渲染 Markdown + 检索索引
├── gensite/usages.go         从 example/ 抽取真实调用点
└── build.sh                  一键生成 + 构建

构建

tools/apidoc/build.sh          # 生成 + 构建到 site_build/
tools/apidoc/build.sh serve    # 本地预览(http://127.0.0.1:8000)

依赖:Go 1.21+、mkdocs-material(pip install mkdocs-material)、 jieba(中文检索分词,pip install jieba)。

两条设计原则

① API 参考从源码生成。 签名、说明、示例全部来自 sdk/*.go 的文档注释。 发现文档不对时,改的是源码注释,然后重新生成。生成页首行有「勿手改」标记。

② 能力边界是可核对的事实,不是印象。 哪些 API 外部插件拿不到, 逐条记在 tools/apidoc/tiers.json,每条都写清可复核的依据 (文件:行号、或 grep 结论)。判断标准是:

依据 含义
tools/hmapdev/templates/proc_main.go.tmpl 的 base.Set* 调用 外部插件运行时实际注入哪些能力
internal/sdk 内置插件用的完整接口(对照出外部缺什么)
internal/plugin/proc/protocol.go 外部插件能发哪些 RPC

文档站上每条「仅内置」告警都带这个依据,读者可自行核对。

为什么这个边界值得单独维护

写这个站时,实测发现文档与源码有三处不符(现已在站内更正):

  1. PluginMgr() 曾被写成「仅内置可用」——实际桥接显式注入了它。 真正的区别是方法数:公开面 3 个,内部面 9 个(两个包里同名不同接口)。
  2. Events() 曾被当作可用的事件订阅入口——实际桥接不注入 subscriber, 外部插件拿到的恒为 nil(SetEventSubscriber 全仓无调用点)。 外部插件的事件订阅实际由生成的运行时走 events.subscribe RPC 完成。
  3. UnregisterOutputChannel 易被当成「可用但会报错」——实际返回 nil, 静默无效(桥不注入 unregister),不报错也不注销。

检索

站内有两套检索,互补:

  • MkDocs 内置搜索(右上角):全文检索,中文走 jieba 分词。
  • 自建 API 检索(首页与 API 参考页的输入框):读 assets/api-index.json, 专门解决「按描述找 API」——搜「注册工具」能找到 RegisterTool, 搜「崩溃」能找到 SetAutoRestart,并可区分公开/仅内置。

自建检索支持四类查询:名称、描述(中英文)、限定符.方法 (如 memory.recall)、签名片段(如 (string) error)。

维护提示

  • 改了 sdk/*.go 的注释或签名 → 重跑 build.sh,改动自动进文档。
  • 改了能力边界 → 改 tiers.json,不要直接改生成的 .md。
  • 新增示例插件 → 自动出现在「示例插件」页的用法表里(扫 example/)。
  • site_build/ 是构建产物,已 gitignore,不要提交。