--- name: obsidian-excalidraw description: 在 Obsidian Excalidraw 修改版中绘制原生可编辑流程图、UML、架构/微架构、电路和多页演示。支持用户指定library的原生导入、自由手绘draw、多边形、立方体、大括号、callout、代码高亮与checkbox,提供手绘/Visio等风格;必须根据真实PNG反馈局部迭代,默认五轮、达标提前结束。 --- # Obsidian Excalidraw:可编辑绘图与 PNG 反馈闭环 ## 执行入口 优先使用已发现的 `drawing_*` 工具,MCP server 与marketplace可能加前缀或缩短过长名称;以真实工具列表/schema为准,不硬编码 `mcp__excalidraw_`。工具成功不是视觉通过;本 Skill 的交付必须包含实际 PNG 检查和 review ledger。 本包包含 Skill、MCP 执行器、Bridge/Feature Engine bundle 和首次连接入口。若 `drawing_setup` 存在,先用 `status` 发现 vault,再在用户选定目标后用 `connect`。没有 MCP 工具时,使用本包 `launcher.py` 的真实 CLI(安装目录由用户环境提供,不从 Skill 目录猜测);不能假定已连接 Bridge。CLI 预览返回 `out_path`,必须用图片读取工具打开 PNG。令牌只在本机私有状态目录,绝不打印或写入提示、图、报告、vault 描述文件和公开仓库。缺 Obsidian/ymjr 插件时明确报告宿主前提缺失,不用原始 JSON 或假图片冒充完成。 ## 默认策略 - 用户只提供内容与关系即可;不要索要元素 JSON、坐标、字体编号。 - 只有缺失信息会改变业务语义,才问一个关键问题;普通布局、配色和间距自行选一致默认值。 - 新图创建独立 `.excalidraw.md`;修改已有图按明确文件绑定。不能直接写 active/first,也不能 clear 重建用户的图。 - 默认平整专业风格:原生 Helvetica 与系统中文 fallback,正文20、标题28、线宽2、roughness0;自定义字体必须通过 discovery 确认,用户要求覆盖默认值。 - 优先原生 shape/text/arrow。图片、公式、ECharts、embeddable 保留真实源引用/配置;不能把整图保存为一张图片。 ## 按需选择图型、风格、图元和素材 - 普通图直接规划;用户说UML/微架构/电路/多页演示、手绘/Visio等时,读取`skill://obsidian-excalidraw/references/diagram-recipes.md`并用`drawing_templates`取真实recipe。 - `drawing_templates(list)`发现图型和style;`get`只提供参考输入;`plan`产生测量后的原生operations,仍需apply、PNG和review。主diagram可加`style:"handdrawn"|"visio"|"blueprint"|"presentation"|"professional"`。 - 用户指定library必须先用`drawing_library(query/get/preview)`检查真实item,优先插入该库,不能拿近似矩形替代ALU等符号。重复名称用item ID消歧,来源错误或资源缺失明确报告。 - `drawing_library(insert)`走原生复制/Hook入口并返回源→新ID、frame、group与可绑定anchor;使用明确token/baseRevision。库preview不是整图完成证据。 - 多个素材与普通节点组合用`drawing_compose`;多页库模板用`drawing_present`。它们分阶段真实提交,失败必须保留已执行集合,不称整笔原子。 - 用户说“draw/手绘笔画”时用原生freedraw;“手绘风格”只是roughness/fill等profile,不混为一种能力。 - draw、多边形、立方体、四向大括号、callout、高亮代码、checkbox、高级连接:按需读取`skill://obsidian-excalidraw/references/native-features.md`,`drawing_primitives`生成真实操作,不调用会弹面板的Action脚本等待用户。 - 多页演示保留原生frame与每页元素,逐页导出并实际看图;不能只看缩小overview就判断所有页可读。未调用真实PPTX导出工具,不声称已经生成.pptx。 - 多页intro可能有多个title/full-name占位;必须按sourceIdMap完整替换,不能只填一个留下旧英文。slides已有原生bullet时新文字不要重复加Unicode项目符号;派生bullet保持同一library instance并纳入原生frame/group。 - 样式和文本字段放在operation的`style`对象,例如`create_text {...,style:{fontFamily,fontSize,strokeColor}}`;不是任意顶层fontSize。没有节点的标题/注释直接create_text,不把空nodes传给图规划器。 ## 新图:自然语言到真实操作 1. 若有 `drawing_setup`,先调用 `status`。未连接时,在用户目标已明确或仅有一个合法 vault 时调用 `connect`;多 vault 歧义才询问。它部署 bundle、生成私有凭据、通过实际 Advanced URI 启动;没装 Advanced URI 则报告返回的准确手动命令,不能声称启动成功。已配置但 Obsidian 重启后用 `start`。然后 `drawing_context(action="discover")` 核对 Bridge、字体与 Engines。无效令牌、缺插件/画布不能假装已有连接。 2. `drawing_context(action="create", filename=描述性名称, foldername="Agent-Diagrams")` 得到 `contextToken`、真实文件与revision。修改已有图则 `action="bind", file_path=明确vault相对路径`。之后所有操作传该token。 3. `drawing_read(context_token)` 读取完整摘要;不是几个选中元素。保留初始状态。 4. 组织简短图描述并调用 `drawing_plan(context_token, diagram)`。规划器使用真实字体/内容尺寸,负责换行、节点尺寸、分层和避障;不要按字数猜宽。 - `kind`: flowchart/architecture/swimlane/freeform。 - `nodes`: `id, shape, label, variant?`,shape用rectangle/ellipse/diamond;`content`支持image/latex/echarts/embeddable;其它复杂几何用实际native operations。 - `edges`: `id, from, to, label?, fromPort?, toPort?, style?`。端口用top/right/bottom/left。循环/回边保留,必要时`feedback:true`。 - `containers`: `id,label,members`;可見背景与表头。`groups`只是一起移动,不替代容器。 - `lanes`: `id,label,members,color?`;实际名称swimlane,接受用户所称swimeline,别写不存在的customData.swimeline。默认竖列泳道+TB流程。 - `layout`: direction TB/LR,nodeGap/rankGap、origin、padding可按用途覆盖;默认通常足够。`position`是scene坐标,可为负。 - 每项logical ID唯一;缺失关系目标必须修正,不能补造用户未要求的业务节点。 5. 将返回的 `operations` **完整**传给 `drawing_apply(context_token, base_revision=plan.baseRevision, operations=plan.operations)`;不要手抄删掉绑定/标签/元数据操作。大输出可通过真实CLI或eval导入DrawingClient完成plan→apply,保留生成的plan/result文件,不写mock。 6. 记录返回的native ID/refs;再读取最终状态。现有插件可能调整容器与箭头,不能只看计划坐标。 图描述示例: ```json { "diagramId": "request-review", "kind": "flowchart", "title": "访问申请流程", "nodes": [ {"id": "submit", "shape": "rectangle", "label": "提交访问申请", "variant": "primary"}, {"id": "review", "shape": "diamond", "label": "身份、权限范围和资源使用条件是否全部通过审核?"}, {"id": "grant", "shape": "rectangle", "label": "发放凭据", "variant": "success"}, {"id": "reject", "shape": "rectangle", "label": "拒绝并说明原因", "variant": "warning"} ], "edges": [ {"id": "submit-review", "from": "submit", "to": "review"}, {"id": "approved", "from": "review", "to": "grant", "label": "通过"}, {"id": "denied", "from": "review", "to": "reject", "label": "未通过", "fromPort": "right"} ] } ``` ## 每轮:check → PNG → 看图 → review → 局部修正 **默认 max_rounds=5。每次当前状态的 check+PNG+视觉review计一轮,初图也计入;不是必须画五遍。** 达到要求立即结束。连续两轮问题/严重度无改善或达到上限时needs_attention,报告剩余问题,不标完成。 1. `drawing_check(context_token, expected=语义断言)`:断言节点存在、方向正确等。读取issues中的native IDs;结构通过不意味着业务或美观通过。 - `expected`示例:`{"type":"label_equals","id":"实际节点或文字ID","text":"完整内容"}`、`{"type":"edge_label","from":"起点ID","to":"终点ID","text":"通过"}`;节点字段是`id`,不是`target`。 2. `drawing_preview(context_token, base_revision=check.revision, scale="auto", padding=20)`:默认预算避免大scale与包缓存内输出。除非用户明确指定外部交付路径,不传out_path,使用本机持久化artifact目录;不要把PNG写进版本化安装包。全图用于整体结构;小字/扩展内容再用ids局部PNG。`complete=false`或资源错误不能当成功。 3. **实际查看返回的PNG**。MCP返回image block;CLI使用`read(out_path)`。没有图像查看能力就记录visual_reviewed=false并明确限制。 4. 检查:内容与方向、长中文完整、文字是否在形状有效区域、表头/正文分离、对齐与间距、连线路径/箭头头/标签、图片/公式/图表/嵌入是否真出现、整体层级与配色。用返回的bounds/transform关联PNG位置和元素ID。 - **程序check=pass仍可能缺标签或不好看**。逐项核对用户要求的所有节点全文与分支标签;不要仅核对edge.from/to存在。普通节点内容用`label_equals`,分支标签用`edge_label`语义断言。 - 长中文菱形不要横向撑成整张图的主视觉。优先增加合法换行与适度高度,保留至少正文内边距;检查决策宽度是否远大于同类节点、是否因此产生多余空白。 - “通过/未通过”应贴近决策出口对应路径且左右归属明确,不贴到整张图的最外缘。可对绑定text的`labelPosition`(0–1的路径比例)作局部调整;默认0.28是起点,不是所有路线都理想。 - 同层分支大小和基线一致;只为给标签空间才增间距,不能把“无重叠”做成过度疏散的大画布。初图用planner默认nodeGap/rankGap,先看PNG再有理由地覆盖。 5. `drawing_review(context_token, revision=preview.revision, preview_id=preview.previewId, visual_reviewed=true, visual_issues=[...], check_result=check, changes_summary=本轮真实改动, max_rounds=5)`。 - 只有实际看图后才填true。 - 视觉问题用稳定code、elementIds、severity error/warning、reason、repair;不拿任意审美分数替代问题。 - `completed`才交付;`continue`按问题修正;`needs_attention`停止自动修改并报告未满足项,不规避ledger换token继续刷轮数。 6. **修复明确问题,而不是每轮重建**:只修改问题对象、绑定文本及必要邻边。`drawing_apply`使用最新revision;局部修正后重复check和PNG。即使只改一行字也需要最终图检查。 停止标准:语义清单完整;无硬错误;必需几何检查无unknown;所有资源完整;当前revision的PNG确实看过;无影响使用的视觉问题。工具错误/无进展不是完成。 ## 局部修正:真实 native operations 先读取目标详细元素:`drawing_read(context_token, ids=[...], detail="full")`。优先这些操作,不直接改scene JSON: - `set_text {target: body或text ID, text:完整新标签}`;长文本先`drawing_measure(..., width=目标有效宽度)`,使用返回的换行text与真实尺寸;必要时resize容器。 - `translate {targets:[ID],dx,dy,includeBoundText:true}`;同时移动容器和已包含的bound text时去重,避免二次位移。 - `resize {target,width,height}`;读取最终容器与邻边状态,不能仅扩大text bbox假装容器已适配。 - `patch_element {target,patch:{x/y/width/height/points/合法样式}}`;线的points是局部坐标,首点[0,0],其余可负。 - `connect {from,to,start:{anchor,mode:"orbit"},end:{anchor,mode:"orbit"},waypoints:[scene点],label?,elbowed:true,style?}`。 - `rebind_arrow`/`unbind_arrow`按实际capabilities字段;不手写单边boundElements。 - `patch_element {target:箭头绑定text ID,patch:{labelPosition:0.2}}`:保持原生绑定而调标签路径位置;实际PNG复核,不能只改x/y却被引擎重新居中。 - `patch_custom_data {target,merge:{安全元数据},remove:[字段路径]}`;是merge,不是patch。 - `set_feature {feature,targets:[ID],config}`用发现的spec;gradient接direction/stops,不接模型生成代码;shadow只有px字符串是像素。 不要将反馈四舍五入的坐标整条回写。不要为了消除穿线删掉跨组关系、缩短业务内容或移用户锁定元素。REVISION_CONFLICT时重新读受影响数据,不覆盖用户新编辑。 ## 扩展与边界 ECharts由真实options保留数据,泳道由真实Engine管理;customData.document/任意gradient代码不是默认接口。PNG对DOM内容需要捕获adapter;无法捕获会标incomplete,不能用边框或空白冒充正文。曲线/旋转检查若unknown,明确剩余限制或改为用户允许的可检查表达,不伪称全部校验通过。 LaTeX先看discovery中的`latex.available`:当前插件源码可能通过独立Excalidraw Extras MathJax组件加载;缺依赖会明确LATEX_PREREQUISITE_MISSING,不要等待一个无人确认的弹窗或拿公式普通文本/假图片替代。 ## 交付 给出真实vault文件、最终PNG、本轮数/ledger状态和剩余问题(若有)。保留原生可编辑场景。不要声称“专业”只因为元素已创建;以最后一次PNG和校验为准。