DSH Plugin Store
Back to home

Fromlan

dsh-godot-tool

Drive the Godot 4.x editor from an AI agent: Godot agent_rpc addon + DeepSeek Harness dsh-tool-godot plugin (loopback TCP JSON-lines bridge, 27 godot_* tools)

Stars
0
Language
TypeScript
Created
Aug 14, 2026
Updated
Aug 14, 2026
Other
GitHub repo

Introduction

Godot Agent RPC —— 让 AI agent 驱动 Godot 编辑器

English | 中文

一对插件,让 AI agent 通过回环 TCP JSON-lines 驱动 Godot 4.x 编辑器:打开/重新加载场景、运行/停止当前或主场景、观察播放错误、检查场景树和脚本、设置项目设置、lint GDScript、列出项目文件以及导出构建。

路径内容运行于
addons/agent_rpc/Godot 编辑器插件(EditorPlugin + EditorDebuggerPlugin)——TCP 客户端、消息分发、播放错误环形缓冲Godot 编辑器进程
dsh-godot-tool/DeepSeek Harness 插件(@deepseek-ai/dsh-godot-tool)——回环 TCP 服务端GodotRpcBridge)+ 27 个 godot_* 面向模型工具DeepSeek Harness

两半使用同一种线上协议:TCP 127.0.0.1:8765(回退 8765–8774)上的换行分隔 JSON、令牌认证握手、仅回环。本文档是唯一参考——先快速开始,再讲线上协议,然后是两半各自的手册。

┌─────────────────────────────┐          ┌──────────────────────────────┐
│  Godot 4.x 编辑器           │  TCP     │  DeepSeek Harness            │
│                             │  JSON-L  │                             │
│  addons/agent_rpc(客户端) │◄────────►│  dsh-godot-tool(服务端)    │
│  EditorPlugin + 调试器      │  8765    │  GodotRpcBridge + 27 工具    │
└──────────────┬──────────────┘          └──────────────┬───────────────┘
               │ 每秒轮询端点文件                       │ 发布
               ▼                                        ▼
      ~/.pi/agent/x-agent-godot-rpc.json   ~/.dsh/godot/endpoint.json
               (插件默认)                  (harness 插件默认)

目录


快速开始

1. 安装 Godot 插件

addons/agent_rpc/ 复制到 Godot 项目的 addons/ 文件夹,然后在 项目设置 → 插件 中启用 Agent RPC

2. 安装 harness 插件

两种方式:

  • 从本仓库(源码):通过 --patch overlay 或项目插件行把 Harness 指向 dsh-godot-tool/src/index.ts,并在组合中加入 dsh-tools
  • 从 harness workspace:如果你在 deepseek-harness 仓库内构建,包位于 packages/extensions/tool-godot@deepseek-ai/dsh-godot-tool);本副本与其保持同步。

3. 让插件指向 harness 端点

插件每秒轮询端点文件。默认是 ~/.pi/agent/x-agent-godot-rpc.json;harness 插件默认发布 $DSH_HOME/godot/endpoint.json。把一边指向另一边:

  • 设置环境变量 AGENT_RPC_ENDPOINT(推荐),或
  • 设置 ProjectSettings 键 agent_rpc/endpoint_file,或
  • 把 harness 插件的 endpointPath 配置为插件的文件路径。

4. 启用你想要的工具

每个 godot_* 工具默认关闭(harness 插件配置中 enabledTools 为空)。显式选择启用:

# dsh cordis.yml
- id: tool-godot
  name: '@deepseek-ai/dsh-godot-tool'
  config:
    enabledTools: ['godot_editor_info', 'godot_run_scene', 'godot_play_errors']

然后启动 harness、打开 Godot 项目,agent 就可以驱动编辑器了。

5. 验证连接

  • 桥开始监听后约 1 秒内,插件会在 Godot Output 面板打印 Agent RPC: connected to …
  • 从 agent 一侧调用 godot_editor_info——端到端通路正常时返回 { godotVersion, projectPath, editedScene, playing }。若失败,对照故障排查表检查。

工作原理

两个进程、一个回环 socket、一个把它们连起来的端点文件:

  1. 先启动 harness(或先启动 Godot——两种顺序都行)。 dsh-godot-tool 插件绑定 127.0.0.1:8765(忙时向上尝试至 8774),生成 32 位十六进制令牌,并原子写入端点文件 { host, port, token } 供插件发现。
  2. 插件每秒轮询该文件,文件变化或消失时自动重连。文件按 AGENT_RPC_ENDPOINTagent_rpc/endpoint_file → 旧默认 ~/.pi/... 的顺序解析。
  3. 首次 TCP 连接时插件发送 editor_ready,携带令牌和 addonVersion;桥认证后记录其 projectPath 并分配 clientId
  4. agent 调用 godot_* 工具 → 桥校验(白名单、工具闸、参数卫生、跨项目路由)→ 发送 JSON 行请求 → 插件对编辑器执行操作 → 以 ok:true/ok:false 应答 → 桥解析工具调用结果。
  5. 播放期间插件推送 play_error 事件进入桥的环形缓冲(上限 50);godot_play_errors 读取它们。插件绝不会自动停止播放——由 agent 调用 godot_stop_scene

线上协议

锁定插件 0.6.3、协议世代 1.0 + 1.2 + 1.3(27 个 RPC 方法)。改动任何一半时,请在同一提交内更新本节。

传输

属性
地址仅回环 —— 127.0.0.1
端口8765,忙时回退到 8765–8774
编码UTF-8、换行分隔 JSON(每行一个对象,无长度前缀,无二进制)
认证插件在 editor_ready 时出示的 32 位十六进制令牌

消息形态

// 请求 —— 服务端 → 插件
type GodotRpcRequest = {
  id: string;        // 调用方的 randomUUID
  method: string;    // 见下方名单
  ...params          // 方法专属参数
};

// 响应 —— 插件 → 服务端(按 id 配对)
type GodotRpcResponse =
  | { id: string; ok: true;  result: unknown; routedTo?: string }
  | { id: string; ok: false; error: string;    routedTo?: string };

// 事件 —— 插件 → 服务端(无 id)
type GodotRpcEvent =
  | { type: "editor_ready"; godotVersion: string; projectPath: string;
      token?: string; addonVersion?: string; clientId?: string }
  | { type: "scene_changed"; path: string; clientId?: string }
  | { type: "play_error"; severity: string; message: string; clientId?: string }
  | { type: "disconnected"; clientId?: string };

分帧规则(0.6.3 修复):用 data.has("method") 区分请求与事件,绝不要data.has("type")list_project_files 接受 type 参数用于过滤,同时携带 methodtype 的请求会被旧启发式静默丢弃。

端点文件

服务端把 { host, port, token } 发布到插件每秒轮询的 JSON 文件(plugin.gd 中的 _endpoint_config_path());文件变化时插件自动重连。

字段类型说明
hoststring复用时必须是 127.0.0.1localhost;其他值被拒绝并重新生成令牌
portnumber1–65535;超出范围则回退
tokenstring32 位十六进制(/^[0-9a-f]{32}$/i);不匹配则回退
versionnumber线路格式版本;当前 = 1
updatedAtstring每次成功监听时写入的 ISO 时间戳

文件原子写入(tmp + 重命名),服务端停止时故意不删除,以便下次启动复用令牌、跳过握手抖动。

方法名单(27 个 RPC + ping

工具(启用时)RPC 方法协议世代
godot_editor_infoget_editor_info1.0
godot_open_scenesget_open_scenes1.0
godot_edited_sceneget_edited_scene1.0
godot_open_sceneopen_scene1.0
godot_reload_scenereload_scene1.0
godot_run_scenerun_current_scene(+ wait_ms1.0
godot_run_main_sceneplay_main_scene(+ wait_ms,≡ F5)1.0
godot_import_resourcesimport_resources(+ 可选 paths1.0
godot_play_errorsget_play_errors(+ 可选 clear1.0
godot_stop_scenestop_scene1.0
godot_get_scene_treeget_scene_tree(+ max_depth1.0
godot_get_node_propertiesget_node_properties1.0
godot_get_debugger_stateget_debugger_state1.2
godot_set_breakpointset_breakpoint(+ condition?remove?1.2
godot_find_unused_resourcesfind_unused_resources(+ root?1.2
godot_get_project_settingget_project_setting1.2
godot_set_project_settingset_project_setting1.2
godot_lint_scriptslint_scripts1.2
godot_export_projectexport_project(+ presetoutput_dirdebug?1.2
godot_list_project_fileslist_project_files(+ type?pattern?limit?cursor?1.3
godot_resolve_uidresolve_uiduid? 异或 path?1.3
godot_wait_for_import_donewait_for_import_done(+ timeout_ms?1.3
godot_list_global_classeslist_global_classes1.3
godot_find_class_name_conflictsfind_class_name_conflicts(+ include_addons?1.3
godot_inspect_scriptinspect_script1.3
godot_list_export_presetslist_export_presets1.3
godot_check_export_templatescheck_export_templates1.3

ping 是协议级健康检查,没有对应的用户工具。白名单位于 dsh-godot-tool/src/protocol.tsGODOT_RPC_ALLOWED_METHODS),工具到方法的门控映射在 GODOT_RPC_METHOD_TOOL;白名单之外的请求在到达桥之前即被拒绝。

超时阶梯

常量用途
GODOT_RPC_DEFAULT_PORT8765监听
GODOT_RPC_FALLBACK_PORT_END8774监听回退
GODOT_RPC_DEFAULT_WAIT_MS3000播放错误窗口
GODOT_RPC_MAX_WAIT_MS15000播放错误窗口上限
GODOT_RPC_BASE_TIMEOUT_MS8000默认请求超时
GODOT_RPC_EXPORT_TIMEOUT_MS5 × 60 000export_project 硬杀
GODOT_RPC_EXPORT_GRACE_MS15 000导出返回后的宽限
GODOT_RPC_GRACE_PERIOD_MS8000断连宽限窗口
GODOT_LIST_FILES_DEFAULT_LIMIT / MAX_LIMIT500 / 5000list_project_files 分页
GODOT_WAIT_DEFAULT_TIMEOUT_MS / MAX30 000 / 60 000wait_for_import_done

播放错误收集

run_current_scene / play_main_scene 清空缓冲、开始播放,并在可配置窗口(默认约 3 秒,上限 15 秒)后返回目前捕获到的错误:

{
  "started": true,
  "playing": true,
  "waitMs": 3000,
  "playMethod": "play_current_scene",
  "errors": [{ "severity": "error", "message": "..." }]
}

来源(rpc_debugger.gd):Output 面板的 ERROR / WARN 消息、调试器错误页、断点命中原因。插件绝不会在出错时自动停止播放——调用方必须调用 stop_scene

安全模型

闸门位置作用
服务端回环绑定bridge.ts —— server.listen(port, '127.0.0.1')内核拒绝非回环绑定
令牌握手editor_ready —— 32 位十六进制比对失败计为 missing_token(插件 < 0.2.0)/ bad_token(令牌过期)
方法白名单protocol.ts —— GODOT_RPC_ALLOWED_METHODS白名单之外在到达桥之前即被拒绝
工具闸(双层)注册 + 分发只注册 enabledTools(模型 schema 永不包含被禁用工具),且桥对每个线上方法重新检查门控工具
参数卫生protocol.ts —— checkHygiene字符串 ≤ 4096、数组 ≤ 512、嵌套字符串 ≤ 4096
set_project_setting 拒绝列表protocol.ts禁止 autoload/*input/*editor_plugins/enabled、调试日志/警告/形状/颜色、TLS 证书包覆盖、project_settings_override/*
跨项目路由bridge.ts请求只到达 projectPath 与调用会话 cwd 共享的客户端
断连拒绝bridge.ts路由到已断连客户端的在途请求以 client disconnected 失败

词汇表(中英对照)

English中文一句话定义
addon插件Godot 编辑器扩展;位于 <project>/addons/<name>/;在 project.godot [editor_plugins] 中声明
EditorPlugin编辑器插件基类在编辑器进程中运行的代码所继承的 Godot 基类
EditorDebuggerPlugin编辑器调试器插件基类钩住 ScriptEditorDebugger 信号,无需派生子进程即可捕获运行时错误
EditorInterface编辑器接口单例打开场景、控制播放、列出打开场景等的静态访问器
ProjectSettings项目设置Godot 的项目级配置存储;键使用 / 分隔路径,如 autoload/Foo
autoload自动加载autoload/* 键下注册的单例脚本。已列入 set_project_setting 拒绝列表
endpoint file端点文件桥发布的 {host, port, token} JSON 文件,插件每秒轮询
handshake握手首次 TCP 连接时发送的 editor_ready 事件,携带插件提供的 tokenaddonVersion
token令牌授权插件与桥通信的 32 位十六进制共享密钥
addonVersion插件版本插件的 plugin.cfg 版本,在 editor_ready 时上报,便于服务端警告协议不匹配
routedTo路由目标请求未指定客户端时桥自动路由到的 clientId
tool gate工具闸双层(注册 + 分发)检查:RPC 被受理前必须启用对应工具
JSON-linesJSON 行协议每行一个 JSON 对象的 UTF-8 流,以 \n 分隔
play error播放期错误run_current_scene / play_main_scene 会话期间捕获的运行时错误/警告
ping健康检查唯一没有对应用户工具的 RPC 方法
ring buffer环形缓冲保存最近 play_error 事件的有界缓冲(上限 50)

Godot 插件(agent_rpc

客户端一半——让 AI agent 驱动编辑器的 TCP JSON-lines 桥:仅回环传输、令牌握手、默认关闭的工具闸。

插件文件夹内容

addons/agent_rpc/
  plugin.cfg        # 插件清单(名称、version="0.6.3"、入口脚本)
  plugin.gd         # EditorPlugin —— TCP 客户端、消息分发、播放错误环形缓冲
  rpc_debugger.gd   # EditorDebuggerPlugin —— 钩住 ScriptEditorDebugger output / debug_data / breaked

没有自动加载、没有场景文件——一切都在编辑器进程中运行(@tool)。

安装

  1. addons/agent_rpc/ 复制到 Godot 项目的 addons/ 文件夹。
  2. 在 Godot 中:项目设置 → 插件 → 启用 "Agent RPC"
  3. 启动你的 agent(如带 dsh-godot-tool 的 DeepSeek Harness)。它监听 127.0.0.1:8765,忙时回退到 8765–8774,并发布插件轮询的端点文件。
  4. 插件约 1 秒内连接成功,Godot Output 面板打印 Agent RPC: connected to …

升级插件后请重新安装,并重新加载项目或重启 Godot

端点配置

插件每秒轮询端点文件并自动重连。文件按以下顺序解析:

  1. 环境变量 AGENT_RPC_ENDPOINT——例如当 DeepSeek Harness dsh-godot-tool 插件发布到 $DSH_HOME/godot/endpoint.json 时指向该路径。(推荐。)
  2. ProjectSetting 键 agent_rpc/endpoint_file——显式的项目内路径。
  3. 旧默认值——~/.pi/agent/x-agent-godot-rpc.json

环境变量优先;两者都覆盖旧默认值。文件本身必须包含 { "host": "127.0.0.1", "port": 8765, "token": "<32-hex>", "version": 1 }

握手

首次 TCP 连接时,插件发送携带 tokenaddonVersioneditor_ready 事件。复用上一个端点文件的令牌,"先启动 Godot、再启动 agent"约 1 秒即可就绪,无需重新安装任何东西。

故障排查

症状可能原因先查什么
无连接,握手失败 missing_token插件早于 0.2.0(editor_ready 不带令牌)plugin.cfg 版本;重装插件
无连接,握手失败 bad_token插件持有过期令牌;服务端已写入新令牌确认两端读取同一个端点文件;重装插件强制重读
run_current_scene 有脚本错误却返回空 errorsEditorDebuggerPlugin 未钩住 ScriptEditorDebugger(调试器 UI 尚未构建,或 Godot 版本差异)打开 Godot 调试器面板,确认插件已激活
run_current_scene 后播放卡住wait_ms 已到但插件从不自动停止这是设计行为——调用 stop_scene
export_project 超过 5 分钟仍挂起无头 Godot 卡在缺失的导出模板或脚本启动桥在导出超时时杀进程;检查 Godot 输出
set_project_setting 被拒 "forbidden prefix"写入 autoload/*input/*editor_plugins/enabled安全模型中的拒绝列表是最终的
list_project_files 总是超时服务端用了旧的 data.has("type") 分帧启发式分帧规则必须是 data.has("method")——见消息形态
lint 失败时编辑器冻结约 30 秒--check-only 在主线程运行使用 plugin.gd 中的线程 worker 模式;_exit_tree 必须等待线程

Harness 插件(dsh-godot-tool

服务端一半——@deepseek-ai/dsh-godot-tool:回环 TCP JSON-lines 服务端外加 27 个 godot_* 面向模型工具。

它做什么

  1. GodotRpcBridgesrc/bridge.ts)——绑定到回环地址的 node:net 服务端,使用插件协议:换行分隔 JSON、令牌握手(editor_ready)、按连接分配 clientId、按 id 关联请求响应,以及捕获 play_error/scene_changed 事件。
  2. 27 个工具src/tools.ts)——每个线上方法一个 defineTool,全部通过桥分发。完整名单见方法名单

插件发布插件每秒轮询的端点文件(默认 $DSH_HOME/godot/endpoint.json,或 Config.endpointPath),因此"先启动 harness,再打开 Godot"大约一秒钟即可就绪,无需重新安装插件。

配置

字段默认值含义
port8765首选回环监听端口;桥会向上尝试至 fallbackPortEnd
fallbackPortEnd8774报告端口耗尽前尝试的最后一个端口。
token自动生成的 32 位十六进制插件必须在 editor_ready 时出示的共享密钥。
endpointPath~/.dsh/godot/endpoint.json插件轮询的端点文件;指向与插件读取的相同文件。
enabledTools[]要注册的工具名。默认空——部署选择启用之前,模型看不到任何 godot 工具。

端点文件原子写入(tmp + 重命名),并在插件卸载时故意保留:下次启动复用令牌,避免握手抖动。

工具闸

enabledTools 是参考桌面实现的双层开关,折叠进一个插件:

  • 注册层——只注册选择启用的工具,因此模型的功能调用 schema 永远不会包含被禁用的工具。
  • 分发层——桥对每个线上方法重新检查门控工具(GODOT_RPC_METHOD_TOOL),因此即使直接调用桥也无法触达被禁用的方法。

导出形态

函数/命名空间插件:导出 name / inject / Config / apply没有 export default。多余的 export default 会经 Loader 的 unwrapExports 折叠模块并丢弃 inject——与 harness postmortem 0001-acp-default-export-drops-inject 记录的同一种失败模式。

模型体验

工具 schema——模型只看到 Config.enabledTools 中列出的工具对应的 godot_* schema;描述会指明线上方法的参数以及任何上下文大小上限(场景树序列化预算、列表分页)。每个启用工具在每次请求中产生固定 schema 成本;工具集不变时前缀稳定。

工具调用结果——每次成功调用原样返回插件的 result 作为规范 JSON 值(例如 get_editor_info{ godotVersion, projectPath, editedScene, playing })。线上 ok:false 或本地拒绝(方法不允许、工具被禁用、参数卫生、未知客户端、跨项目路由、超时、客户端断连)以 Error: <message> 呈现。结果令牌随插件响应增长,受其序列化预算约束(5000 节点场景树、500/5000 文件分页、50 条错误环形缓冲)。

已知局限

  • 线上协议锁定参考插件——27 方法白名单、超时阶梯和拒绝列表镜像 agent_rpc 0.6.x;更新的插件协议世代需要同步扩展 src/protocol.ts
  • 断点不支持条件表达式——Godot 4 断点 API 忽略条件;set_breakpoint 报告 conditionIgnored,模型只能依赖行断点。
  • play_error 捕获依赖编辑器调试器 UI 时序——EditorDebuggerPlugin 钩住 ScriptEditorDebugger;在部分 Godot 版本上,钩子只在调试器面板构建后挂接。依赖错误收集前请先用真实编辑器验证。
  • 仅单一活动客户端路由——多个 Godot 实例连接时,未指定的调用路由到第一个认证客户端;clientId 选择尚未暴露为工具参数。

开发

仓库布局

addons/agent_rpc/          # Godot 编辑器插件(客户端一半),GDScript
  plugin.cfg / plugin.gd / rpc_debugger.gd
dsh-godot-tool/            # Harness 插件(服务端一半),TypeScript
  src/bridge.ts            # GodotRpcBridge —— 回环 TCP 服务端、握手、路由
  src/protocol.ts          # 方法白名单、超时阶梯、参数卫生、拒绝列表
  src/tools.ts             # 27 个 godot_* 工具定义
  src/endpoint.ts          # 端点文件发布 / 读取 / 删除
  src/index.ts             # 插件入口(name / inject / Config / apply)
  tests/                   # vitest 套件(bridge、protocol、tools、loader-composition)

运行 harness 插件测试

TypeScript 一侧用 vitest 测试;tests/fake-addon.ts 通过真实回环 socket 伪造 Godot 插件,因此套件无需 Godot 编辑器即可覆盖实际线上协议:

cd dsh-godot-tool
pnpm exec vitest run

套件:bridge.spec.ts(传输、握手、路由、超时)、protocol.spec.ts(白名单、卫生、拒绝列表、端点 schema)、tools.spec.ts(工具闸)、loader-composition.spec.ts(导出形态)。

用真实 Godot 编辑器做冒烟测试

.smoke-test/ 是一个最小的一次性 Godot 4 项目(主场景打印 SMOKE_OK from Godot 4.7),自带 addons/ 下安装的插件。它被排除在 git 之外;用于手工验证线上通路:

  1. 在 Godot 编辑器中打开 .smoke-test/project.godot(该项目的插件已启用)。
  2. 启动启用了 tool-godot 的 harness;桥发布端点文件。
  3. 运行场景(F6):Output 面板显示 Agent RPC: connected to … 和打印行;然后用 godot_editor_info / godot_run_scene / godot_play_errors 从 agent 侧驱动。

保持文档同步

README 把线上协议锁定到插件版本和协议世代。改动任何一半(新方法、超时常量、配置字段)时,请在同一提交内更新:

  • dsh-godot-tool/src/protocol.ts —— 白名单、超时阶梯、卫生上限、拒绝列表、端点 schema。
  • 上文方法名单超时阶梯安全模型表。
  • 插件变化时同步 plugin.gd 中的 ADDON_VERSIONplugin.cfgversion

兼容性

插件 0.6.3、harness 插件 0.1.0-rc.5@deepseek-ai/dsh-godot-tool)、协议世代 1.0 + 1.2 + 1.3(27 个 RPC)。已在 Godot 4.4 stable4.7 stable(Windows)上测试。自本仓库补丁起,插件读取 AGENT_RPC_ENDPOINT / agent_rpc/endpoint_file;旧的 ~/.pi/... 默认值仍可用。新插件版本可能增加方法,但 1.0 集合保持不变。

许可证

MIT —— 见 LICENSE