实时与无头模式
每次调用时,服务器都会通过编辑器保存在 ~/.erd-editor/ide/ 中的锁文件,查找持有该文档的编辑器。
装有 ERD Editor 的每个 VS Code 窗口和每个 Obsidian 仓库窗口各保留一个锁文件,而 JetBrains IDE 则为整个 IDE 保留一个锁文件,其中列出在该 IDE 中打开的每个项目。
编辑器关闭时会删除其锁文件。
服务器找到的结果决定了编辑去向何处。
| 找到的情况 | 编辑的行为 |
|---|---|
| 某个编辑器的工作区、仓库或已打开的项目包含该文档,或者该编辑器已打开该文档 | 实时模式。 必要时在 ERD Editor 中打开文档,加入编辑会话,并在那里应用变更。编辑会立即显示,并像编辑器保存你自己的编辑那样被保存,参见保存。 |
| 没有编辑器 | 无头模式。 加载文件、应用变更,然后替换该文件。erd_save 无事可做。 |
| hub 已关闭的编辑器 | 拒绝编辑。 读取仍然有效,从磁盘读取。在打开的编辑器底下写入文件的变更可能会在其下次保存时被覆盖,因此服务器不写入任何内容。 |
hub 已开启、但所用协议与服务器不同的编辑器:对于服务器 1.0.0,即 VS Code 扩展 3.x、Obsidian 插件 0.x,或者 JetBrains 插件 0.9.0 或 0.10.0;对于 1.0.0 之前的服务器,即扩展 4.0.0 或更高版本,或者插件 1.0.0 或更高版本 | 拒绝编辑,读取也不例外,以 protocolMismatch 被拒绝。消息会指出需要更新的一方:扩展或插件,或者服务器,参见更新。 |
在 Windows 上,以同一文件的另一条路径持有该文档的编辑器:智能体通过本机的网络共享或映射驱动器指定该文档(例如 \\localhost\C$\…),而编辑器以其驱动器路径持有它,或者反过来 | 拒绝编辑,读取也不例外,以 invalidPath 被拒绝。消息会指出编辑器持有该文档所用的路径;请用该路径再次调用。 |
| 在 Windows 上,Windows 不允许智能体访问的编辑器:智能体未以管理员身份运行时以管理员身份启动的编辑器,或者智能体在沙箱中运行时的任何编辑器 | 拒绝编辑,读取也不例外,以 hubUnreachable 被拒绝,并附带一条说明原因的消息。请以相同的权限运行编辑器和智能体,例如不使用管理员权限重新启动编辑器。 |
编辑的结果会注明它运行的模式,即 live 或 headless,被拒绝的编辑则会说明原因。
每次调用都会重新查找,因此打开或关闭编辑器后,下一次调用会随之改变去向。
有多个编辑器持有该文档时,已打开该文档的编辑器优先于只为包含它的文件夹提供服务的编辑器;在为文件夹提供服务的编辑器之间,文件夹层级最深的那个优先。 出现平局时(例如两个编辑器都已打开该文档),由锁文件最后发生变化的那个编辑器胜出。 因此,位于 VS Code 工作区文件夹内的 Obsidian 仓库中的文档会交给 Obsidian,除非 VS Code 已打开它而 Obsidian 没有。
对同一文档的调用按照到达服务器的顺序逐个执行。对不同文档的调用则并行执行。
实时模式
智能体会像又一位协作者一样加入编辑器。 它的编辑会同时到达打开该文档的每个编辑器,它的焦点也会像协作者的焦点一样绘制在它正在编辑的表和单元格上,参见 focusTracker。
读取从不会打开编辑器。文档尚未打开时,编辑会在 ERD Editor 中打开它,且不会夺取键盘焦点。
保存
每个编辑器都会像保存你自己的编辑一样保存智能体的编辑。
在 VS Code 中,智能体的编辑会像你自己的编辑一样把标签页标记为未保存,只有在文档保存时才会写入磁盘。
erd_save 会像 VS Code 自身的保存命令一样,通过 VS Code 保存文档。你也可以自己保存,使用 Ctrl + S (Windows/Linux) 或 ⌘ + S (Mac)。
在带有未保存的智能体编辑时关闭编辑器,会像其他任何未保存的变更一样询问是否保存。
Obsidian 会在编辑停止约两秒后保存智能体的编辑,关闭标签页时则会不经询问地保存它们。
JetBrains IDE 会在编辑停止后不到一秒写入它们,关闭标签页时会写入仍待写入的内容;标签页从不会显示为已修改。
在这两者中,erd_save 都会立即写入它们。
erd_save 会先等待最多两秒,直到编辑器持有智能体所做的每一次编辑。
当编辑器无法确认这一点,或者没有写入文件时,它会以 notSaved 被拒绝:VS Code 会在文件于磁盘上发生变化时让标签页保持未保存状态,而 JetBrains IDE 未能写入文件,例如在有对话框打开期间,或者文件无法写入时。
在 VS Code 和 JetBrains IDE 中,对没有任何待保存内容的文档调用 erd_save 会成功,并让文件保持原样。
每次编辑都已保存时(JetBrains IDE 会自行做到这一点)就属于这种情况;只要此后的每次变更都是被锁定挡在文件之外的变更,例如在 Viewport 锁定时滚动或缩放,或者在 Canvas Type 锁定时切换标签页,情况就一直如此。所有锁定默认都处于开启状态。
即便如此,JetBrains IDE 无法写入的文件仍会被拒绝。
当编辑器在智能体最后一次编辑之后关闭了该文档时,智能体的下一次调用会附带一条说明:只有在编辑器关闭之前已经保存,这些编辑才会存在于文件中。
Undo
erd_undo 会撤回智能体所做的最后一次编辑,而绝不会撤回你的编辑,erd_redo 则会重新应用它。
编辑器自身的 Undo 恰好相反:它撤回你的编辑,而绝不会撤回智能体的编辑,因为从其他编辑器到达的变更不会记录在你的历史记录中。
有几种编辑不会在编辑器中产生 Undo 记录:设置工具中的 erd_set_database 和 erd_set_database_name,以及 erd_resize_memo。
将分组移动总计不足 20 像素(横向与纵向的距离相加)的 erd_move_table_group 也不会产生 Undo 记录,不过分组会停留在移动后的位置。
不改变任何内容的调用同样不会产生 Undo 记录:erd_set_column_primary_key、erd_set_column_unique、erd_set_column_not_null、erd_set_column_auto_increment、erd_set_index_unique 或 erd_set_index_column_order 所设置的值与文档已有的值相同;erd_add_index_column 添加索引中已有的列;erd_set_table_group 指定的表已在该分组中(或者 groupId 为 null 时,表已不在任何分组中);erd_move_table_group 移动到分组已在的位置;erd_resize_table_group 设置的矩形与分组已有的矩形相同;在没有任何表的文档上调用 erd_sort_tables;或者 mode 为 append、却没有带来任何表的导入(对于 erd_import_json,则是既没有带来表,也没有带来备注)。
erd_undo 会跳过这些编辑,并在结果中列出它们。
其他编辑,例如 erd_change_relationship_type、erd_change_relationship_on_delete、erd_change_relationship_on_update、erd_change_table_group_name、erd_change_table_group_color 和 erd_set_ddl_script,即使所设置的值与文档已有的值相同,也会产生 Undo 记录。
出现以下情况时,智能体的 Undo 历史记录会结束,并在结果中附带一条说明:
- 智能体重新加入文档,例如在编辑器把智能体从文档中移除之后。
- 编辑器退出,或者关闭该文档并停止为其提供服务,智能体转而继续编辑磁盘上的文件。
- 某个编辑器接管了智能体正在磁盘上编辑的文档。
服务器还会关闭智能体 30 分钟内没有调用过的文档,Undo 历史记录也随之消失,并且不会附带说明。
编辑器消失时
只要有编辑器持有某个文档,服务器就绝不会自行退回到编辑文件。 连接断开时,它会重新连接。 只有在编辑器已经退出,或者已经关闭该文档且不再列出它或包含它的文件夹时,服务器才会编辑文件,并在结果中说明这一点。 这种情况发生在:你关闭位于编辑器所服务的所有文件夹之外的图时(在 VS Code 中,即从工作区之外打开的图)、你在 Obsidian 中关闭 ERD Editor 插件时,以及你在 JetBrains IDE 中关闭持有该文档的项目或在那里关闭该插件时。 位于编辑器所服务的文件夹之内的图即使已关闭,也仍归该编辑器管理,智能体的下一次编辑会重新打开它。
仍在运行、但锁文件已消失且连接在未关闭该文档的情况下就已断开的编辑器,会以 hubGone 拒绝下一次编辑。
消息会说明如何释放该文档:在 VS Code 中,重新加载该窗口,或者关闭它,让智能体直接编辑文件;在 Obsidian 中,重新开启 ERD Editor 插件,或者关闭该窗口;在 JetBrains IDE 中,重新开启该插件,或者退出 IDE。
在两种情况下,读取会改为读取磁盘上的文件,并附带一条说明:尚未在编辑器中保存的编辑不包含在内。这两种情况是:持有该文档的编辑器的 hub 已关闭时,以及上面的 hubGone 情况。
无法连接到编辑器 hub 的读取会像编辑一样,以 hubUnreachable 被拒绝。
无头模式
没有编辑器为该文档提供服务时,每次编辑都会加载文件、应用变更,然后把文件写回。
写入会先写到文档旁边一个名为 .<name>.<id>.tmp 的临时文件中,再用它替换文档,因此文档绝不会处于写了一半的状态,但下文所述 Windows 上就地写入的情况除外。
在最后这一步之前,服务器会检查文件在调用期间是否在磁盘上发生了变化。
如果发生了变化,则不写入任何内容,重新加载文件,并以 conflict 拒绝该调用。智能体会再次调用。
在两次调用之间发生变化的文件只会被重新加载,而智能体在此之前的 Undo 历史记录会被丢弃。
只读文件会保持原样,编辑会以 readonly 被拒绝:所有者没有写入权限的文件,或者在 Windows 上带有只读属性的文件,例如尚未签出的 Perforce 或 TFVC 文件。
请使其可写,然后再次调用。读取仍然有效。
如果在智能体编辑磁盘上的文件期间,有编辑器开始为该文档提供服务,那一次编辑会以 hubAppeared 被拒绝,不写入任何内容。下一次调用会通过该编辑器进行编辑。
在 Windows 上还适用另外两条规则:
- 拥有不同于其文件夹的独立权限的文档会被就地写入而不是被替换,以便保留这些权限,临时文件随后会被删除。在写入期间读取该文档的程序可能会读到无法解析的文本。
- 被其他程序打开占用的文件无法被替换,因此服务器会在最多两秒内重试。每次重试都会先重新查找编辑器,而在此期间开始为该文档提供服务的编辑器会以
hubAppeared拒绝写入,如果其 hub 已关闭则以blocked拒绝。如果两秒后文件仍被占用,则不写入任何内容,重新加载文件,调用会失败,并附带一条引用系统错误的消息。
拒绝编辑
即使 hub 已关闭,VS Code 窗口也会保留其锁文件:dineug.erd-editor.agentHub.enabled 关闭时、工作区不受信任时,或者其 hub 无法监听时。
Obsidian 仓库窗口在 Coding agents 关闭时,以及其 hub 无法监听时,会在 hub 关闭的状态下保留其锁文件。
JetBrains IDE 在 Coding agents 关闭时、其 hub 无法监听时,以及 IDE 退出期间,会在 hub 关闭的状态下保留其锁文件。
对这类文档的编辑会以 blocked 被拒绝,因为打开的编辑器下次保存时可能会覆盖写入文件的变更。
读取仍然有效,从磁盘上的文件读取。
若要让智能体编辑,请按照消息针对该编辑器给出的说明重新开启 hub:在 VS Code 中,信任该工作区并开启该设置,或者重新加载窗口;在 Obsidian 中,开启 Coding agents,或者重新加载 Obsidian;在 JetBrains IDE 中,开启 Coding agents,如果它已经开启,则重启 IDE。
JetBrains IDE 还会以 hubDisabled 拒绝修改仅由其不信任的项目持有的文档。
智能体仍然可以读取这类文档,erd_list_documents 会将其列为 readonly。请信任该项目,然后再次调用。
不保留锁文件的编辑器不提供任何保护,即使图在那里处于打开状态,智能体也会编辑磁盘上的文件。
在 Linux 上以 Flatpak 形式安装的 Obsidian 或 JetBrains IDE、没有 JCEF 的 JetBrains IDE,以及 hub 无法启动的 JetBrains IDE 都属于这种情况,参见配置 Obsidian 和配置 JetBrains IDE。
3.0.0 之前的 VS Code 扩展和 0.9.0 之前的 JetBrains 插件同样不保留锁文件,因为它们没有 hub。
文档
文档由 path 指定,可以是绝对路径,也可以是相对于服务器工作目录的路径。
- 新文档为
.erd.json。带create的erd_open_document会创建文件,并为没有扩展名的名称加上.erd.json。与编辑器中新建的图一样,新文档的所有锁定都处于开启状态,因此在编辑器中滚动、缩放、切换标签页,或者选择其他 Code Generator 语言、名称大小写或括号类型,永远不会改动文件。没有任何工具能单独开启或关闭某个锁定:这需要你在编辑器的 Settings 标签页中进行。以replace模式调用的erd_import_json会把所有锁定替换为它所加载的文档中的锁定,参见导入。 - 已有的
.erd、.vuerd和.vuerd.json文件同样可以打开。其他扩展名的路径会以invalidPath被拒绝。 - 在 Windows 上,包含 Windows 无法按原样存储的名称的路径,会在读取或写入文档之前以
invalidPath被拒绝,读取也不例外:包含冒号或其他 Windows 拒绝的字符的名称,例如orders:v2.erd;设备名称,例如NUL.erd或CON.erd,不区分大小写;或者以点或空格结尾的名称。请重命名,例如用-代替:。 - 编辑器无法读取的文件,例如残留合并冲突标记的文件,会以
invalidDocument被拒绝并保持原样。它绝不会被当作空图加载后再写回。
智能体只通过工具修改文档,并被告知绝不要自己写入文件。
erd_list_documents 会列出文档及其 path、open、active、dirty 和 readonly。
它会询问为工作目录提供服务的编辑器(按与文档相同的方式选出),先列出在其中打开的图,再列出它所服务的 ERD 文件:VS Code 窗口的工作区文件夹中、Obsidian 仓库中,或者 JetBrains IDE 中打开的每个项目中的文件。
否则,它会列出工作目录下的 ERD 文件,其中只读文件会标记为 readonly,而在 Windows 上,Windows 无法按原样存储的名称会被略过。