# godot-docs —— 面向 DSH 的离线 Godot 文档工具插件 这是一个 [DSH](https://github.com/deepseek-ai)(DeepSeek Harness)插件,把本地的 **Godot 官方文档**(`godot-docs` 仓库或其 `*.rst.txt` 导出)变成 Agent 可用的工具。 Agent 不再凭记忆回答 Godot 问题(记忆通常是 Godot 3.x 或更老的 4.x),而是从与当前项目 引擎版本一致的文档里查证,并给出所引用的文件与行号。 > 仓库: · English: > [README.md](README.md) ``` 文档目录 ──▶ 索引(类、成员、正文词元)──▶ godot_docs_* 工具 ──▶ Agent ``` ## 为什么 * **版本正确**:索引中的文档就是本项目的权威依据;插件会自动识别文档版本(例如 `4.7`)。 * **签名精确**:`godot_docs_member("CharacterBody2D","move_and_slide")` 返回真实签名、 默认值、修饰符与说明,并附带文件行号。 * **查询很快**:1600 页 / 32 MiB 文档,单次搜索约 25–90 ms。 * **完全离线**:不访问网络,索引全部来自本地磁盘。 ## 工具一览 | 工具 | 作用 | | --- | --- | | `godot_docs_search` | 全文检索(all / classes / tutorials),返回摘录与 `相对路径#L行号`;命中规范页时带 `convention_topic` 标记 | | `godot_docs_class` | 类参考:继承链(**祖先与直接子类双向**)、描述、教程链接、**枚举成员及取值**、完整成员表(属性/方法/信号/常量/枚举/注解)及精确行号,并列出可继承到的成员 | | `godot_docs_member` | 单个成员的完整信息:签名、参数、默认值、说明、所在行(可用 `kind:name` 指定类型);继承成员会沿继承链解析并给出 `declared_on`;枚举会列出全部取值,常量会给出数值 | | `godot_docs_find_member` | 反向查找:哪些类声明了同名的成员(如 `signal:body_entered` 查出所有拥有该信号的类) | | `godot_docs_project_settings` | 查询某个设置项或整棵分支(`debug/gdscript/warnings/` 会列出全部 GDScript 警告名),或校验真实的 `project.godot` 并报出文档中不存在的键 | | `godot_docs_get` | 读取整页或某一节,返回清理过 RST 标记的带行号文本(`path#L120-L180`、`path#Method Descriptions`) | | `godot_docs_code` | 抽取官方示例代码(`gdscript`、`csharp`、`glsl`、`cpp` 等),供改写而不是凭空编 API | | `godot_docs_conventions` | 查官方**开发规范**:GDScript 风格、项目/场景组织、静态类型、@export、文档注释、警告系统、单例取舍、信号、C# 风格与 API 差异、着色器风格、文件路径、i18n、性能、线程安全、编辑器插件等,并给出对应页面路径 | | `godot_docs_project_search` | 在**本项目自己的源码**里做字面/正则检索:看某 API 既有用法、找全部调用点、检查推荐写法是否已遵守 | | `godot_docs_api_check` | 校验标识符(`Class`、`Class.member`)、整段 GDScript/C#,或**整个项目目录**——脚本**以及 `.tscn`/`.tres` 场景与资源**:对文档中不存在的名字给出 `文件:行号` 的调用点 | | `godot_docs_status` | 当前索引了哪些文档树、识别到的版本、页数/类数、缓存状态、探测路径与解析错误 | | `godot_set_docs_path` | 把文档目录写入插件配置(立即生效) | 插件还会注入三段系统提示(system prompt):先查文档、没有文档时如何配置路径,以及 (重要)按引擎自己的规范写代码,而不是照搬其他引擎的习惯或记忆中的做法。 ## 不只是 API,还有规范 这份文档树本身就包含本项目的编码规范。`godot_docs_conventions` 把主题或别名映射到权威页面 (并告诉你该页面是否存在于当前文档树),`godot_docs_search` 会在结果里标出规范页,而 `godot-docs:conventions` 提示段会列出文档确立的要点:GDScript 风格指南的命名与代码顺序、 静态类型、用 `@export` 暴露可调参数、用信号代替轮询、保持节点树扁平并拆进场景、 用 `%UniqueName` 代替长节点路径、不要滥用 autoload、运行时写 `user://` 而不是 `res://`、 可翻译文本用 `tr()` 且不要拼接、耗时工作交回主线程而不是在线程里随意调引擎 API、 不要无视引擎警告。 共收录 **40 个规范主题**,每一个都由自检脚本验证确实存在于该文档树中:GDScript 风格/静态类型/ @export/文档注释/警告系统/格式化字符串、C# 风格、C# 与 GDScript 的 API 差异、C# 语言特性、 项目与场景组织、场景与脚本取舍、autoload、信号、分组、资源、节点与对象取舍、逻辑与数据、 数据存储取舍、接口、通知、idle 与物理帧、可重写回调、暂停、输入、多分辨率、文件路径、 国际化、性能、线程安全、着色器风格、编辑器插件、单元测试等。 ## 校验真实代码 `godot_docs_api_check(paths=[...])` 会遍历项目自己的**脚本与场景**,报告**本文档版本里不存在的** 引用,并给出每处 `文件:行号`。它刻意保守——误报的代价高于漏报——只断言可证的部分: 脚本部分: * 文档中存在的类的 `Class.member`,成员沿**继承链**解析(`Node.get_property_list` 在 `Object` 上; `TCPServer.new` 是语言层构造而非缺失方法); * 类型可证的变量的成员访问:`is` 判断、`as` 转换、构造调用,或有文档的返回类型; * 绝不报告:字符串字面量(`"res://levels/Node2D.tscn"`)、容器键(`Dictionary`/`Array` 属性包)、 被 `:=` 遮蔽的变量、`self.`/`super.` 成员、GDScript 语言内置成员。 `.tscn`/`.tres` 场景与资源部分: * **节点类型**必须是文档中的类(`type="Sprite2Dxx"` 会被报出); * **节点属性与子资源属性**按该节点的类校验,因此拼错或改名的属性无需打开编辑器就能发现; * 由节点自身脚本声明的属性——`@export var max_health`——会从项目脚本解析出来,**包含继承来的** (`extends Entity`),并包含**被实例化场景根脚本**的导出变量; * **信号连接**按 `from` 节点解析出的类校验; * 属于格式/编辑器而非类 API 的键会被识别并计入统计,而不是报错:`layout_mode`、 `anchors_preset`、`theme_override_*`、`metadata/*`、各种块头; * `.tres` 的根 `[resource]` 块按 `gd_resource type` 校验。 `godot_docs_project_settings(path=<项目目录>)` 对 `project.godot` 做同样的事:报出所有本文档版本 未收录的键及其行号与相近候选。`config_version` 与 `application/config/features`(引擎写入) 以及用户自定义的 `[input]`、`[autoload]`、`[layer_names]`、`[editor_plugins]` 段被视为结构而非 API。 在作者本机的 7 个真实 Godot 项目上,脚本检查约 6000 处 API 用法只报出 2 处,且都是真错误 (`Camera3D.get_environment()` 实际只存在于 `World3D`;`ThemeDB.get_fallback_font()` 是属性不是方法)。 ### 这类调用到底搜的是哪个项目 读取项目文件的工具以**会话工作区**为基准:省略 `path`/`paths` 时从工作区开始,相对路径按工作区解析, 工作区自身或其上级目录里存在 `project.godot` 才是"这个项目"。宿主进程自己的目录永远不作为基准——在桌面版里 那就是 DSH profile 目录,而一次静默扫描 `~/.dsh/profiles/` 却把它当成项目的搜索,会以 "0 条匹配"的形式回答。 当被搜索目录及其上级都没有 `project.godot` 时,返回值会明说而不是猜:`godot_docs_project_search` 返回 `found_project_godot: false`、`resolved_by: "start"`,并在 hint 里指出该根目录只是回退;`godot_docs_api_check` 也会在汇总里标注该路径。对文档树或散放的脚本目录来说这是正常情况;要搜真实项目请显式传 `path=`。 ## 索引了哪些数据 所有工具的回答都来自首次调用时从文档树构建的索引(1600 页约 2.5 秒),并缓存为 JSON (`~/.dsh/godot-docs-cache/index-.json`,约 30 MiB,约 170 ms 重新载入): * 每页元数据:标题、继承链、描述、章节标题、正文长度; * 1078 个类上的 **25340 条成员锚点**(属性/方法/信号/常量/构造/运算符/注解/私有回调/主题项)及精确行号; * **788 个枚举、5601 个取值**(含 `Variant.Type` 这类带点号的枚举名); * **可继承成员表**,因此类只继承来的成员也能解析; * **941 个有文档的项目设置**及其键名与行号; * 用于检索的正文词元倒排索引。 两个查询不落盘、按需派生(各约 20 ms,避免让缓存继续膨胀):**成员反查索引** (`godot_docs_find_member`)与**子类表**(`godot_docs_class`)。 ## 安装 插件是标准 DSH bundle(ESM 插件 + `cordis.patch.yml`)。在本 `package.json` 所在目录执行: ```bash dsh plugin --profile add <本地路径或 git 地址> ``` 本仓库的 git 地址为: ```bash dsh plugin --profile add git+https://github.com/TheoiNabiy/godot-docs-dsh-plugin.git ``` 也可以手动写入 profile 的 `package.json` 依赖与 `dsh.profile.bundles`,再启动 profile。 bundle 层会注册组合行: ```yaml - insert: - id: tool-godot-docs name: godot-docs ``` 文档路径也可直接写进 profile 的 `cordis.patch.yml`(或用 `godot_set_docs_path`、或插件 卡片上的 `docsPath` 字段): ```yaml - id: tool-godot-docs name: godot-docs config: docsPath: D:\Godot\godot-docs-master ``` ## 文档来源与优先级 以下来源按顺序使用,先解析到文档树的那一层生效: 1. 工具参数 `docs_path`; 2. 插件配置 `docsPath`(可写多个目录,用 `;` 或换行分隔); 3. 会话工作区及其上层目录(因此把文档检出直接作为工作区打开时无需任何配置); 4. 约定位置(`~/godot-docs`、`~/Documents/godot-docs`、`C:/godot/godot-docs`、 `/usr/local/share/godot-docs`、`/opt/godot-docs`)。 判定标准:目录下存在 `classes/class_node.rst.txt`。显式传入的 `docs_path` 具有权威性—— 若它不是一个文档树,工具会直接说明原因,而不会悄悄改用手头其他文档。 ## 索引与缓存 首次调用会构建索引(1600 页约 2.5 秒):每页元数据(标题、继承链、描述、章节标题、正文 长度)、全部 `.. _class_X_method_y:` 成员锚点,以及正文词元倒排索引。随后会持久化为 JSON (`~/.dsh/godot-docs-cache/index-.json`,约 18 MiB),并以「页数 + 最新 mtime」校验, 之后每个会话加载仅需约 70 ms。若所有缓存位置都不可写,则每个进程重新构建索引,功能不受影响。 ## 配置项 | 字段 | 类型 | 说明 | | --- | --- | --- | | `docsPath` | string | 需要索引的文档目录。DSH ≥ 0.2 上为 volatile 字段,GUI 表单可原位编辑。 | ## 开发 ```bash node test/run.mjs [文档目录] # 39 项自检:注册工具并逐一调用验证 node test/bench.mjs [文档目录] # 索引构建 / 缓存 / 搜索耗时 ``` `test/node_modules` 内是 `@deepseek-ai/dsh-tools` 与 `@deepseek-ai/schemastery` 的最小 桩实现,`test/hooks.mjs` 负责把这两个导入重定向过去,使插件能脱离 harness 单独启动。 ## 许可 MIT。