godot-asset-planner — Godot 资产与项目目标统一管理插件
一个 DSH(DeepSeek Harness)插件,把 Godot 游戏项目的资产管理与项目目标整合到同一套工具里:注册资产、创建目标、按关键词/目标查询、生成关联状态报告。数据通过 DSH 的 storage 服务持久化到本地 JSON 文件,重启后自动加载。
作者:LINinLIN-0079 · 许可证:MIT(见 LICENSE)
截图
资产管理器(资产列表 / 拖拽上传 / 搜索筛选 / 目标看板 / 预览区) | 场景树查看器(Godot 节点树实时读取与编辑) | Git 版本控制(状态 / 提交 / 分支 / 差异)
![]() |
![]() |
![]() |
文件结构
| 文件 | 说明 |
|---|---|
godot-asset-planner.ts |
插件源码(TypeScript,运行时零依赖):4 个工具 + /gap REST 路由 + 拖拽文件上传。包主入口(main / exports["."]) |
lib/client.js |
浏览器 half(exports["./client"]):better-sidebar 三个 tab(资产管理器 / 场景树查看器 / Git 版本控制),window.__ModuleLoader__.load 工厂格式,只 require('react') |
cordis.patch.yml |
bundle 补丁层(dsh.bundle.patch):插入插件行。安装后由 profile 启动自动合并 |
cordis.yml |
--patch 一次性加载用的补丁清单(同内容覆盖文件) |
game-dev.yml |
「游戏开发模式」覆盖文件(同 --patch 或 profile 补丁) |
package.json |
包清单:dsh.bundle + dsh.client 双声明(单包 = host + client),"type": "module" |
tsconfig.json |
编辑器类型检查(erasableSyntaxOnly + verbatimModuleSyntax) |
test-plugin.mjs |
功能测试:真实 json 后端 + 9 个工具 + REST 路由 + 上传 + 重启持久化 + Godot 场景桥实时测试(headless 读树/增删改回写) |
test-render-client.mjs |
浏览器 bundle SSR 冒烟:模块加载/工厂物化/双 tab 注册/组件渲染(含 SceneTreeView) |
debug-scene-bridge.mjs |
场景桥调试脚本:临时 Godot 项目 + 真实 console 二进制,打印每次 dump/编辑结果 |
快速开始
方式一:dsh plugin 安装(推荐,发布形态)
本插件是单包双 half:dsh.bundle 提供 host 插件(工具 + REST 路由),同一个包的 dsh.client 声明让 client-modules 自动把 lib/client.js 纳入浏览器启动清单——一条命令装好 host + client:
# 从 npm / GitHub 发布后:
dsh plugin --profile web add godot-asset-planner
# 本地开发(本仓库直接链接):
dsh plugin --profile web add link:D:\deepseek\my-plugins
安装命令会把 godot-asset-planner 追加到 profile 的 dsh.profile.bundles 层栈,profile 启动时合并包的 cordis.patch.yml 完成挂载。重启 dsh web / 桌面应用后生效。
方式二:写入 profile 补丁(--patch / 热重载)
桌面版 DeepSeek Harness 每次启动读取 C:\Users\ASUS\.dsh\profiles\web\cordis.patch.yml,且该文件支持热重载——编辑保存后,正在运行的 GUI 会重新组合。
把下面这段追加到该文件里(name 为包名,从 profile 的 node_modules 解析):
- insert:
- id: godot-asset-planner
name: godot-asset-planner
或在 harness 目录用命令行一次性加载:
cd D:\deepseek\DeepSeek Harness\resources\harness
D:\deepseek\DeepSeek Harness\resources\node\node.exe --import tsx/esm apps/cli/src/bin.ts web --patch D:\deepseek\my-plugins\cordis.yml
⚠️
--patch必须放在--host/--port等应用参数之前:一旦出现第一个未识别的参数,其后的选项会原样透传给 web 应用。
验证补丁组合(免启动,打印组合后的完整树):
node "D:\deepseek\DeepSeek Harness\resources\harness\apps\cli\lib\bin.js" --profile web --dump-config --patch ./my-plugins/cordis.yml
注意:
--dump-config会重写 profile 根文件cordis.yml(内容固定为空列表,幂等),需要对该目录有写权限。
工具清单
除
godot_list_projects外,所有工具都支持可选参数project_id(缺省为default项目);项目列表可用godot_list_projects查询。资产、目标、标签、关联、报告均按项目隔离。
| 工具 | 输入参数 | 功能 |
|---|---|---|
godot_list_projects |
无 | 列出全部规划项目(id + 名称,可选 Godot 目录路径),供其它工具指定 project_id |
godot_register_asset |
asset_name(必填), asset_type(model/sound/scene/script/image/other, 必填), file_path(必填), linked_goal(可选), tags(可选数组), project_id(可选) |
注册游戏资产;可关联到已存在的目标;可带初始标签;名称重复或关联不存在的目标会失败 |
godot_create_goal |
goal_name(必填), goal_description(必填), due_date(可选) |
创建项目里程碑/目标;名称重复会失败 |
godot_query_assets |
keyword(可选), linked_goal(可选) |
按大小写不敏感关键词(匹配名称/路径/类型/关联目标)和/或目标名查询资产;都不给则返回全部;两者为 AND 关系 |
godot_asset_report |
format(text/markdown, 必填) |
生成全部目标及其关联资产、未关联资产清单和统计的状态报告,按格式渲染 |
godot_add_asset_tag / godot_remove_asset_tag |
asset_name(必填), tag(必填, ≤40 字符) |
给资产添加/移除用户标签;重复添加/移除不存在标签为无操作 |
godot_link_asset_to_goal / godot_unlink_asset_from_goal |
asset_name(必填), goal_name(必填/可选) |
建立/解除资产与目标的关联;解除时传错目标名会失败 |
godot_set_asset_done |
asset_name(必填), done(布尔, 必填) |
标记资产完成状态——目标的进度条由关联资产中 done 的比例驱动 |
godot_delete_asset |
asset_name(必填) |
永久删除资产记录(仅移除规划器记录,磁盘文件不受影响);资产不存在会失败 |
godot_update_asset |
asset_name(必填), file_path/asset_type/linked_goal/tags/done(均可选) |
更新资产字段(只改提供的字段);linked_goal 传空串清除关联;tags 传数组整体替换(去重、每项 ≤40 字符);资产不存在/非法类型/未知目标会失败 |
数据持久化
- 存储服务:DSH
storage服务(inject: ['tools', 'storage'])。 - 后端:
@deepseek-ai/dsh-storage-json(web profile 已挂载,根目录$DSH_HOME/storages/,即C:\Users\ASUS\.dsh\storages\)。 - 单元:KV 单元
godot_asset_planner(文件godot_asset_planner.json),内含assets与goals两张表,每条资产/目标记录独立原子落盘。 - 可通过
cordis.yml的config.unitName指定其它单元名(须匹配^[a-z][a-z0-9_]*$)。 - 插件卸载/重载时会关闭单元;进程退出由后端统一收尾。
多项目(planner projects)
- 概念:资产/目标按「规划项目」隔离(记录带
projectId,存储 key 为`${projectId}::${name}`);旧数据(无projectId)自动归入常驻的default(默认项目),无需迁移。 - 项目管理:客户端工具栏左侧项目切换器(下拉列出全部项目 + 当前项目名),新建/重命名/删除/从 Godot 目录添加在「管理项目」弹窗完成;当前选中项目持久化(prefs 单元
currentProject),跨会话保留。 - 切换视图:切换项目后重新拉取
/gap/state,资产列表、看板、预览、标签、关联、报告、场景树、操作日志全部显示该项目数据。 - 删除项目:确认后连同该项目的资产与目标一并删除(不可恢复);
default项目不可删除。 - Godot 目录发现:「管理项目 → 扫描 Godot 项目目录」把
godotScanRoot(默认D:/Godot)下发现的含project.godot的目录一键加入项目列表;添加时会主动读取项目文件——宿主验证project.godot存在(否则拒绝)并解析config/name作为项目名(未提供名称时),记录其path;创建后自动批量导入项目资源为资产(res://相对路径、按扩展名推断类型;跳过project.godot本身、.godot/.git/bin/obj/build等缓存构建目录及无法识别的文件;重名跳过并计数,上限 3000 个防阻塞)。 - REST:
GET /gap/state?project=<id>指定视图(缺省用当前项目);POST /gap/projects(创建)//gap/projects/rename//gap/projects/delete//gap/projects/select(持久化当前项目);GET /gap/projects/candidates(Godot 目录候选);各写路由支持 bodyprojectId(缺省当前项目)。 - 工具:11 个
godot_*工具可选project_id(缺省default),配合godot_list_projects查询项目 id。
实现要点
- 运行时零依赖:插件只用
import type(编译期类型),没有任何运行时 import——Node 的类型剥离(Node ^22.19 || >=24)直接加载.ts源文件,无需打包或 tsx。 - 原始 JSON Schema 注册:工具定义直接传给
ctx.tools.register(DSH 支持 raw-schema 工具自校验参数),校验逻辑在execute内完成。 - JSON Schema 子集约束:
required只能用对象级数组(如required: ['name']),不能写在属性内部({ type: 'string', required: true }会被真实注册器拒绝——本插件的 schema 已按此修正)。 - 写串行化:KV 单元不保证并发写顺序,插件内部用 promise 链把变更串行化。
- 生命周期:单元懒打开(每个后端同一单元只能有一个活句柄),通过
ctx.effect在插件 fiber 销毁时关闭。 - 工具与 UI 共用同一套核心操作:4 个工具与
/gapREST 路由都调用registerAssetCore/createGoalCore/queryAssetsCore/buildReportCore,模型与界面永远看到同一份数据。 - REST 表面按需挂载:路由通过
ctx.inject(['webServer'], ...)注册(组合条件式),等 webserver 就绪后生效;headless 等无 web 的 profile 自动退化为纯工具插件。 - 工具名带
godot_前缀,避免与其它插件的全局工具名冲突。
游戏开发模式(game-dev profile)与可视化界面
自定义模式(Agent 预设 + profile)
游戏开发模式 = Agent 预设(新建会话下拉可选)+ host 平面插件(工具/REST/UI 已在 web profile 挂载):
① Agent 预设(出现在新建会话的预设下拉里,与“标准模式”并列)
C:\Users\ASUS\.dsh\.agent-presets\game-dev\
├── preset.yml # name: 游戏开发模式 / description / order: 2
└── agent.cordis.yml # 游戏开发 persona + 标准模式全部工具行
新建会话时在预设下拉选择「游戏开发模式」→ 会话即被激活:Agent 以 Godot 开发助手身份工作。客户端右侧的「Godot 资产管理器」以 dsh-better-sidebar 的一个 tab 呈现(+ 菜单 → Godot 资产管理器,或侧边栏 tab 栏点击图标),所有会话可见(管理的是全局项目数据,不绑定会话)。
为什么插件行不在预设里?
godot-asset-planner打开 storage KV 单元(同一单元仅允许一个活句柄)并注册共享 webserver 路由——按会话挂载会在第二个会话冲突。因此插件挂在 host 平面(profile 补丁),预设只贡献 persona 与工具指引,两者组合即为完整模式。
② game-dev profile(命令行独立模式)
C:\Users\ASUS\.dsh\profiles\game-dev\
├── package.json # bundles: dsh-base + dsh-web-app(即“标准模式”)+ godot-asset-planner
└── cordis.patch.yml # 插件行(bundle 层已插入,这里可只留 config 覆盖)
启动(与桌面启动器相同的源码启动方式):
cd D:\deepseek\DeepSeek Harness\resources\harness
D:\deepseek\DeepSeek Harness\resources\node\node.exe --import tsx/esm apps/cli/src/bin.ts --profile game-dev
端口默认 3080;如需其它端口把
--host 127.0.0.1 --port 3081追加在末尾。dsh在 PATH 时可简写dsh --profile game-dev。
my-plugins/game-dev.yml 是同一内容的独立覆盖文件,两种用法:
- 覆盖到任意 web 能力 profile:
dsh web --patch ./my-plugins/game-dev.yml; - 或把其中的
- insert:块放进某个 profile 的cordis.patch.yml。
⚠️ 桌面版启动器(Electron)固定启动
webprofile。若日常用桌面版,把game-dev.yml的 insert 块放进C:\Users\ASUS\.dsh\profiles\web\cordis.patch.yml(本机已配置好),重启桌面应用即可。
客户端界面(Godot 资产管理器,better-sidebar tab)
- 形态:注册为 dsh-better-sidebar 的三个 tab(
ctx.betterSidebar.registerTab):「Godot 资产管理器」(idgodot-assets,order 60)、「场景树查看器」(idgodot-scene,order 61)、「Git 版本控制」(idgodot-git,order 62),均single: true——侧边栏本身的布局(吸附左右、调宽、折叠、会话持久化)全部由 better-sidebar 提供,无需自绘。 - 依赖:需要已安装
dsh-better-sidebar(web profile 已装 v0.12.2);插件inject: ['betterSidebar'],better-sidebar 缺席时本插件等待该服务。 - 主题:全部使用 DSH 主题 token(
--dsw-alias-*)加中性回退色,适配亮/暗主题;图标为内联 SVG,无 emoji。 - 功能(多面板工作区:自由拖动标题栏、拖拽边框调大小、双击最大化、关闭后从工具栏「面板」菜单重开;详见下方「多面板布局」章节。默认「默认」预设 = 资产列表(左 40%)+ 目标看板(右 60%)+ AI 助手(底部)):
- 资产列表面板:列表(名称/类型/路径/关联目标/标签)+ 行内发送到对话按钮(插入
@名称 <res://路径>(磁盘:绝对路径)到当前会话输入框——光标处插入,未聚焦输入框时追加到末尾,经conversation.input.setDraft公开服务,与 better-sidebar 的草稿插入同一路径;/gap/state为每个资产附加diskPath(res://解析到所属项目根的绝对路径,绝对路径原样),引用同时带上磁盘位置,模型可直接读取文件)+ 行内删除按钮(确认后移除记录)+ 拖拽上传(拖入后补类型与关联目标)+ 高级搜索与筛选:- 工具栏导入为下拉菜单(导出=↑箭头、导入=↓箭头,语义对调):导入配置备份(JSON)(合并/覆盖恢复)或 导入文件夹(两步弹窗:①弹出窗口输入文件夹完整路径 → 宿主
/gap/dir/scan递归读取该路径下所有文件;②再弹出标签窗口,选择路径下文件夹名(候选 chips 多选)或输入自定义标签,确认后/gap/dir/import一次为全部文件批量注册(按扩展名推断类型、绝对路径引用、重复名计为失败);/gap/assets与/gap/upload路由新增可选tags初始标签、重传合并标签); - 搜索栏(Ctrl+F 聚焦)实时过滤名称/路径/类型/标签/目标;
- 筛选系统(筛选面板,默认收起):名称、路径(
res://或磁盘路径均可)、标签多选、类型、关联目标、创建日期范围;带「清除筛选」; - 视图切换(三种):文件名(紧凑单行,仅文件名+大小提示)、双排(双列卡片:类型图标/路径/标签/目标)、表格(名称/类型/大小/标签/目标/操作列——第三种为补充);
/gap/state为资产附加size(磁盘文件字节数,文件不存在时省略)驱动大小列与排序; - 排列方式切换:名称、文件大小、标签名称、创建时间、类型、目标、完成状态(补充后四项),支持升序/降序切换;
- 点击资产行自动打开预览区面板显示详情(预览是独立面板,无需手动打开)。
- 工具栏导入为下拉菜单(导出=↑箭头、导入=↓箭头,语义对调):导入配置备份(JSON)(合并/覆盖恢复)或 导入文件夹(两步弹窗:①弹出窗口输入文件夹完整路径 → 宿主
- 预览区面板:选中资产的预览(可折叠、可拖动上边缘调高 120–480px);头部显示注册路径与磁盘位置(
diskPath,res://已解析为绝对路径,便于复制/让模型读取),并有编辑按钮(弹窗修改路径/类型/关联目标/标签/完成状态,POST /gap/assets/update,只改变更字段):- 图片:内联大图(
GET /gap/file服务注册资产文件),点击放大为全屏覆盖层(右上角关闭按钮 / Esc / 点击背景关闭); - 音效:Web Audio 播放/暂停 + 可拖动进度条(拖动 seek,显示当前/总时长)+ 音量滑块(0–100%);
- 模型:OBJ 统计顶点/面数,GLTF 统计顶点/三角面(3D 预览为未来功能);
- 脚本:轻量语法高亮(注释/字符串/关键字/数字);
- 场景:节点总数 + 节点类型分布;
- 预览区内可添加/移除标签(回车或按钮)。
- 图片:内联大图(
- 目标看板面板:目标以卡片展示——名称(悬停显示完整描述)、进度条(关联资产中已完成的百分比)、截止日期(过期标红)、已关联资产数;支持按截止日期/进度/创建时间排序;卡片点击展开关联资产明细(含完成勾选);顶部资产 dock 点击多选 + 拖拽到目标卡片建立关联、拖到「未关联」区解除关联(HTML5 DnD,拖拽高亮 + 自定义拖拽缩略图)。
- 标签面板(4.2,默认关闭):全部标签列表——颜色圆点 + 标签名 + 关联资产数 + 资产名,点击即按该标签筛选资产列表。
- 关联面板(默认关闭):按目标分组的资产清单 + 未关联资产区。
- 报告面板(默认关闭):一键生成(text/markdown)+ 面板内预览 + Blob 下载。
- 场景树面板:复用场景树查看器组件(headless 读树/编辑)。
- Git 版本控制面板(默认关闭,也可从第三个 tab「Git 版本控制」打开):见下方「Git 版本控制」章节。
- AI 助手面板:工具清单 + 当前数据摘要 + 会话提示(对话在主聊天窗口进行)。
- Toast:所有操作成功/失败即时反馈(内容区底部,自动消失)。
- 资产列表面板:列表(名称/类型/路径/关联目标/标签)+ 行内发送到对话按钮(插入
- 后端新增:资产类型扩展 image/other(上传按扩展名归类:png/jpg/svg→图片);标签工具
godot_add_asset_tag/godot_remove_asset_tag;关联工具godot_link_asset_to_goal/godot_unlink_asset_from_goal与完成状态godot_set_asset_done(资产done标志驱动看板进度条,均持久化到 storage);路由新增POST /gap/assets/tags、/gap/assets/link、/gap/assets/unlink、/gap/assets/done、GET /gap/file(仅服务已注册资产的文件,内容类型按扩展名、8MB 上限——预览数据通道)。 - 通信:同源 JSON fetch 调用 host 插件的
/gap/*路由(state/assets/goals/upload/tags/link/unlink/done/export/import/layout/file/report/git),与 9 个工具共用核心操作,持久化在 storage。 - 打包形态:单包双 half——
godot-asset-planner.ts是 host 插件(exports["."]),lib/client.js是浏览器 bundle(exports["./client"])。包同时声明dsh.bundle(插入 host 行)与dsh.client(platform: "web"),client-modules 扫描 loader 行解析到本包后自动把lib/client.js纳入浏览器启动清单并服务/plugins/godot-asset-planner/client.js。浏览器 bundle 手工写成window.__ModuleLoader__.load工厂格式(id: 'godot-asset-planner',与包名一致),只require('react')(seed 词),无需构建步骤。
场景树查看器(第二个 tab)
- 形态:注册为 better-sidebar 的第二个 tab(id
godot-scene,文档+节点 SVG 图标,标题「场景树查看器」,order 61)。 - 数据来源:Godot
--headless实时读取(不依赖 GodotMCP / godot-bridge / 打开中的编辑器)。宿主把两段 GDScript(dump.gd读树、edit.gd写回)写入临时目录,用Godot*_console.exe --headless --path <项目> --script <runner>.gd -- <场景路径> <ops>运行,从 stdout 解析脚本打印的 JSON。场景必须先注册为资产(路由白名单),项目根通过配置godotProject或在godotScanRoot(默认D:/Godot)下发现解析。 - 功能:
- 场景选择器(列出已注册的 scene 类型资产)+ 刷新;选择记住在 localStorage,重开自动恢复;
- 节点树:Godot 风格彩色图标(2D/3D/UI/动画/通用按类着色)+ 节点名 + 类型 + **可见性(眼睛)/可编辑(铅笔)**状态,缩进层级,展开/折叠(默认全展开,含「全部展开/全部折叠」);
- Ctrl+Shift+F 节点搜索:匹配子串高亮 + 命中节点的祖先自动展开;「清除搜索」恢复;
- 右键上下文菜单:添加子节点(内联名称 + 常用节点类型下拉)、重命名(内联输入,Enter 确认/Esc 取消)、复制子树、删除(弹窗确认,无法撤销)、定位(树内高亮 + 滚动,展开祖先);
- 底部状态栏:节点总数 · 所属项目 · 场景根节点名。
- 每次编辑都是真实的 headless Godot 运行(
POST /gap/scene/edit),成功即写回 .tscn 文件并以 Toast 反馈。
- 已知限制:「跳转到 Godot 编辑器中该节点」需要编辑器桥接(GodotMCP / godot-bridge),未安装——UI 用树内「定位」替代并在菜单里注明。
- 新后端路由:
GET /gap/scene/projects(扫描发现的项目根)、GET /gap/scene/tree?path=(dump 场景节点树,{root, nodes:[{name,path,type,visible,editable,children}]})、POST /gap/scene/edit({path, ops:[{op:'add'|'rename'|'copy'|'delete', ...}]},逐 op 执行并保存)。参数/操作类错误返回 400(ClientRouteError),Godot 不可用返回 500。 - 桥接实现要点:
--path <项目>必须带,否则res://无法解析;Windows 需 console 版 exe(GUI 版不写 stdout);脚本只用显式类型(Godot 4 把从 Variant 推断类型当作错误);操作路径与 dump 一致——根节点路径即根名(如Root),子节点Root/Child,_find先剥离等于根名的首段;根节点禁止删除;copy用duplicate(15)(深度复制)+ 重设 owner。
面板体验增强(4.x)
- 4.1 数据导入/导出(工具栏「导出」「导入」按钮):
- 导出:
GET /gap/export返回{format:'godot-asset-planner', version:1, exportedAt, goals, assets}完整配置 →JSON.stringify+ Blob +<a download>下载为godot-planner-backup-<日期>.json。 - 导入:选择 JSON 文件后弹窗选择合并(追加新数据,重名跳过)或覆盖(清空两张表后重建);
POST /gap/import {mode, data}。非法记录(缺 name / 非法类型等)跳过并计数,不会让整个导入失败;返回{goalsImported, assetsImported, goalsSkipped, assetsSkipped}。 - 宿主实现:
KvUnit增加deleteRecord(覆盖模式先按loadAll().tables逐键删除);所有写入走既有写串行化链。
- 导出:
- 4.2 标签系统(增强版):
- 标签颜色:10 色预定义调色板(
#FF6B6B #4ECDC4 #45B7D1 #96CEB4 #FFEAA7 #DDA0DD #F4A261 #F7DC6F #BB8FCE #85C1E9),按标签名确定性哈希取色——同名同色,无需持久化颜色字段。 - 资产列表的标签显示为圆角色块 + 文字(
renderTagChip:色点 + 半透明底色描边),点击即筛选该标签下的资产(与筛选面板联动)。 - 「标签」视图:全部标签 + 关联资产数 + 资产名,点击跳回资产视图并筛选。
- 标签颜色:10 色预定义调色板(
- 4.3 最近操作记录(面板底部「操作日志」区):
- 内存存储(模块级 store,会话期间有效,刷新即清空,不持久化);上限 100 条。
- 记录:上传/创建目标/关联与解除/完成状态/标签增删(资产、目标 tab)+ 场景编辑(场景树 tab)——跨 tab 共享同一份日志。
- 每条一行(溢出省略),悬停
title显示完整内容;点击跳转:资产→打开/选中资产列表面板,目标→打开/展开目标看板面板,场景→激活场景树 tab;导出/导入类条目不可跳转。 - 「清空」按钮清空日志。
- 4.4 面板设置(右上角齿轮弹出):
- 默认展开/折叠(立即开合面板)、默认宽度(滑块 280–600px,350ms 防抖保存)。
- 自动保存到 storage(复用
/gap/ui-prefs,KV 单元godot_asset_planner_ui);仅当用户在设置面板修改某项时才通过props.store.reduce(better-sidebar store,panelOpen/width字段)精确应用对应字段——store 引用存放在 ref 中保持 reducer 稳定,挂载时不覆盖 better-sidebar 自身持久化的面板几何,因此拖拽调宽、toggle 开合等 better-sidebar 原生操作永远优先,不会与之冲突。
多面板布局(自由工作区)
把资产管理器 tab 拆成可自由拖动、调整大小的子面板工作区(需求 1.x):
- 面板清单(9 个,工具栏「面板」下拉开关):
- 核心 5 个:资产列表(搜索/筛选/列表)、目标看板(排序/进度/拖拽关联)、场景树(复用 SceneTab 组件,headless 读树/编辑)、AI 助手(工具清单 + 当前数据摘要 + 会话提示——对话本身在主聊天窗口进行,客户端无法直接驱动 LLM)、预览区(选中资产的预览与标签编辑)。
- 附加 4 个(默认关闭,可从面板菜单打开):Git 版本控制、关联、标签、报告。
- 交互:
- 拖动标题栏移动位置;拖拽 8 个边框/角手柄调整大小(最小 12%×8%);拖动中的面板显示高亮描边(拖动指示器)并置顶;
- 关闭按钮隐藏面板(工具栏「面板」菜单勾选重新打开);
- 双击标题栏最大化/还原(最大化时其余面板隐藏,标题栏出现「还原」按钮)。
- 面板间 1px 边框分隔线;每个标题栏 = 图标 + 名称 + 还原 + 关闭。
- 预设布局(工具栏下拉,3 个):默认(资产列表左 40% + 目标看板右 60%,AI 助手底部全宽)、开发(场景树左 30% + 资产列表中 40% + 预览区右 30%)、管理(目标看板全屏)。
- 持久化:每次移动/缩放/开关/最大化/预设切换后 400ms 防抖保存到 storage(新增
GET/POST /gap/layout,存 ui-prefs 单元的global.layout——savePrefs改为合并写,互相不覆盖);下次打开自动恢复。 - 技术实现:browser bundle 受「仅
require('react')、零构建」硬约束,无法引入 react-grid-layout / react-mosaic-component——改为自研轻量布局(约 250 行PanelWorkspace:归一化 0–1 坐标 + pointer events 拖动/缩放 + ResizeObserver 测量),功能与交互完整覆盖需求;布局状态通过宿主/gap/layout路由持久化,面板内容以contentOf(id)配置注入。 - 宿主侧:
WorkspaceLayout归一化校验(坐标 clamp 0–1、未知面板 id 丢弃、maximized白名单);KvUnit无新增能力(复用setGlobal)。
Git 版本控制(第三个 tab + 工作区面板)
- 形态:独立组件
GitPanel被两处复用——better-sidebar 第三个 tab(idgodot-git,「Git 版本控制」,Git 分支图标)+ 工作区面板(工具栏「面板」菜单打开)。 - 目录选择:顶部下拉列出
godotScanRoot/godotProject发现的项目根;选择记忆在 localStorage。安全白名单:所有/gap/git/*路由先校验目录属于已发现项目(否则 400);diff 的文件路径做穿越防护(resolve 后必须仍在项目目录内)。 - 功能(1.1):
- 状态查看:
git status --porcelain -b(core.quotepath=false避免中文路径转义)解析为 已修改 / 已暂存 / 未跟踪 三组 + 当前分支;非仓库返回isRepo:false并显示「初始化 Git 仓库」按钮(git init)。 - 提交:多行 textarea +
git add -A && git commit -F -(消息经 stdin 传入,支持多行);成功/失败即时反馈。 - 推拉:
git push/git pull(120s 超时);执行期间顶部显示进度提示("正在执行 git push…"),按钮禁用防重入。 - 分支管理:当前分支 chip + 统计(修改/暂存/未跟踪数);切换下拉(
git checkout);新建输入框 + Enter(git checkout -b,创建并切换)。 - 文件差异:点击文件行 →
git diff(已修改)/git diff --cached(已暂存)/ 直接读文件逐行加+(未跟踪);Diff 视图行级语法着色(+绿 /-红 /@@蓝 / 文件头灰),点击行加载,底部面板显示,可关闭。
- 状态查看:
- 操作反馈(1.2):每次操作写入面板底部「执行日志」(成功 ✓ / 失败 ✗,悬停看详情),失败附带详细错误 + 解决建议(宿主
gitHint:未配置身份 → 提示git config;认证失败 → 检查凭据/SSH key;无远程 →git remote add origin;无上游 →git push -u;合并冲突 → 手动解决等);操作也记入共享操作日志(不可跳转)。 - 宿主路由:
GET /gap/git/projects(自动发现 + 用户导入目录的并集)、POST /gap/git/import-dir(导入任意存在的本地目录到白名单,持久化到 ui-prefs 单元的global.gitDirs)、GET /gap/git/status?dir=、GET /gap/git/branches?dir=、GET /gap/git/diff?dir=&file=&status=、POST /gap/git/init|commit|push|pull|branch|checkout(gitOp统一封装node:child_processspawn + 120s 超时;失败返回{ok:false, error, hint},HTTP 恒为 200 由 ok 判定)。 - 导入目录(1.x 交互补充):目录下拉旁「导入目录」按钮弹窗输入路径(可在文件资源管理器复制路径粘贴),或直接把本地目录拖放到 Git 面板(Electron 环境
File.path可用时);宿主校验目录存在后加入白名单并持久化,重启后仍在。
整合与启动步骤(一键到 tab)
以下示例以本机(Windows +
$DSH_HOME=C:\Users\ASUS\.dsh)为例;路径请按你的环境替换。
- 安装插件(发布形态,一条命令装好 host + client):
dsh plugin --profile web add godot-asset-planner(本地开发:dsh plugin --profile web add link:<本仓库路径>,会作为符号链接进入 profile)。 - 确认 profile 补丁含 config 覆盖(可选:
godotProject/godotBin/uploadRoot/unitName);确认预设目录$DSH_HOME\.agent-presets\game-dev\存在;确认dsh-better-sidebar已装(bundle 层含better-sidebar行)。 - 重启 harness 进程(bundle 层变更与新的 tab 注册需重启生效):桌面版托盘 → 退出 → 重新打开。
- 打开右侧边栏 →
+菜单或 tab 栏点「Godot 资产管理器」(Godot 三角图标)→ 使用多面板工作区(工具栏:项目切换器 / 布局预设下拉 / 面板开关 / 导出 / 导入 / 设置);或点「场景树查看器」(文档+节点图标)→ 选择已注册的 .tscn 场景查看/编辑节点树(需重启后宿主含场景桥路由)。 - 上传文件默认落在
$DSH_HOME\godot-uploads\;想直接进 Godot 工程目录,在 profile 补丁的 config 里加uploadRoot。
测试
node my-plugins/test-plugin.mjs # 宿主:工具 + REST + 持久化 + 多项目 + Godot 场景桥(真实 headless)
node my-plugins/test-render-client.mjs # 客户端:SSR 渲染三 tab + 工作区 + 场景树 + Git + 项目切换器
test-plugin.mjs 覆盖:模块导出面(name/inject/apply)、12 个工具注册、目标/资产创建、全部参数校验失败路径(重复、未知目标、非法枚举、空串)、关键词/目标查询、text/markdown 报告渲染、REST 路由全流程(state/goals/assets/upload/report、400/404、base64 解码落盘、重传刷新)、"重启后数据仍在"的持久化验证(真实 @deepseek-ai/dsh-storage-json 后端 + 临时文件)、导出/导入(GET /gap/export 版本化文档、合并模式跳过重名、追加新数据、覆盖模式清表重建、非法记录跳过计数、非法 mode/data 400)、diskPath 解析(/gap/state 将 res:// 资产解析为项目根下的绝对磁盘路径、绝对路径原样)与 size 附加(磁盘文件字节数、缺失省略)、初始标签(register/upload 路由与工具支持可选 tags、重传合并标签)、文件夹批量导入(/gap/dir/scan 递归扫描 + /gap/dir/import 一次注册全部文件并按文件夹名打标签、重复名计失败不崩溃、缺失目录失败、/gap/dialog/open-directory 非 Electron 环境优雅降级)、删除资产(工具 + 路由:删除记录、状态消失、未知资产 400/拒绝)、更新资产(工具 + 路由:改路径/类型、清关联、整体替换标签去重、设 done、只改提供字段、未知资产/非法类型/超长标签/非数组标签拒绝)、工作区布局(GET/POST /gap/layout 默认值、存取、坐标 clamp、非法面板 id 丢弃、prefs 保存不抹掉 layout)、多项目(项目创建/切换/隔离/重命名/删除连带数据、?project= 视图覆盖、从 Godot 目录添加:读取 project.godot 校验与取名、自动批量导入项目资源(res:// 路径、类型推断、排除 .godot 缓存与无法识别文件))、Git 版本控制(真实 git 临时仓库:projects 发现、非仓库 isRepo:false、init、status 解析未跟踪/已修改、本地身份 commit、干净工作区、modified/untracked diff、路径穿越拒绝、分支创建/切换/列表、无远程 push 失败带建议、未知目录 400、空提交信息 400、import-dir 导入任意目录并入白名单、缺失目录失败),以及 Godot 场景桥实时测试(找到 Godot*_console.exe 时自动跑;临时项目建树 → 注册场景 → dump 树 → add/rename/copy/delete 逐 op 回写并复核新 dump 与 .tscn 内容 → 未注册场景/删根/父节点缺失/ops 非数组等 400 路径;找不到二进制则跳过并提示设置 GODOT_BIN)。
test-render-client.mjs 覆盖:bundle 执行与 window.__ModuleLoader__.load 工厂交接、require('react') 物化、apply() 注册三个 better-sidebar tab(id/标题/order/single/组件/图标)、GodotAssetTab 工具栏(布局预设下拉/面板下拉/导出/导入/设置齿轮)+ 工作区加载态 + 操作日志空态、tagColor 调色板 + renderTagChip 色块、buildAssetRef(引用含磁盘路径、路径相同时省略、缺省容忍)、KanbanView 排序/进度/逾期/focusGoal 展开、SceneTab 空态提示与搜索栏、SceneTreeView 正常/折叠/搜索自动展开/内联重命名/内联添加五种渲染路径、PanelWorkspace 面板标题/data-panel-id/内容注入/关闭按钮/最大化隐藏其余面板、GitPanel 无项目提示/刷新/导入目录/执行日志空态、无 emoji 断言。
参考
- Smalldy/godot-bridge:DSH 插件 +
cordis.patch.yml加载模式的参考实现(通过游戏内 TCP 服务驱动 Godot 4.x)。 - 官方工具插件示例:
packages/fs/tool-fs(ctx.tools.register/defineTool/output.render的规范写法,及docs/cookbook/adding-a-tool.md)。
依赖与鸣谢
本插件运行在 DeepSeek Harness(deepseek-ai/DeepSeek-Harness)之上,并直接依赖以下组件:
| 依赖 | 版本 | 用途 | 来源 / 许可证 |
|---|---|---|---|
| dsh-better-sidebar | 0.12.2 | 客户端 UI 的侧边栏容器:本插件的「Godot 资产管理器 / 场景树查看器 / Git 版本控制」三个 tab 通过其 ctx.betterSidebar.registerTab 服务注册;面板几何(拖拽、调宽、折叠)由它提供 |
github.com/omdsh-dev/DSH-better-sidebar · MIT |
@deepseek-ai/dsh-storage-json |
web profile 内置 | 数据持久化后端(KV 单元 godot_asset_planner / godot_asset_planner_ui → $DSH_HOME/storages/*.json) |
DeepSeek Harness 工作区包 |
@deepseek-ai/dsh-tools / dsh-tool-* |
harness 内置 | 宿主工具注册、shell/fs/jobs 等运行时能力 | DeepSeek Harness 工作区包 |
| Godot Engine | 4.x(headless console 版) | 场景树查看器/编辑器:通过 Godot*_console.exe --headless 真实读写 .tscn |
MIT(Godot 引擎本体) |
特别鸣谢
- omdsh-dev / DSH-better-sidebar(MIT):本插件的所有侧边栏 UI 都依赖它提供的 tab 注册服务与面板交互能力,特此鸣谢。
- DeepSeek Harness 团队:
tools/storage/webServer/ 预设组合等基础设施。 - Smalldy / godot-bridge:插件加载模式与 Godot 桥接思路的参考。
如果你在使用本插件,请一并感谢以上项目的作者。
故障排查
- Node 版本:加载
.ts需要 Node ^22.19 || >=24(默认类型剥离)。桌面版自带resources\node\node.exe(v24)。 - 移动项目后:
test-plugin.mjs/debug-scene-bridge.mjs里file:///D:/deepseek/my-plugins/godot-asset-planner.ts的绝对路径需同步更新(测试脚本直接加载源码,不走包解析)。 - headless 等 profile 没有 storage:
storage/storage-json/storage-domain是 web bundle 的行;在其它 profile 使用本插件前需先补上这些行(在已有 storage 的 profile 上重复添加会报duplicate-backend)。 - 插件没生效:用
--dump-config --patch确认行已进入组合树;查看启动日志中是否有failed to apply loader entry godot-asset-planner的报错。



No comments yet. Be the first to write one.