Files
deta-agent-plugins/plugins/studio/skills/aml-design/SKILL.md
T
ringo 7d3f9e2933
CI / contract (push) Has been cancelled
refactor(plugin)!: 插件改名 studio、新增 writer、统一本机 stdio 管道
命名结构(品牌=市场,产品=插件):市场名保持 deta;插件 deta → studio(displayName DETA Studio),新增 writer(DETA Writer)。安装标识 studio@deta / writer@deta;MCP 服务名 studio_mcp / writer_mcp,可同时安装。plugins/deta → plugins/studio(git mv 保留历史),新增 plugins/writer。

连接形态统一为单一本机 stdio 管道:.mcp.json 与 cordis.patch.yml 均声明 stdio → bin/deta-mcp.sh --profile <产品>,并按官方插件写法补 cwd: "."(缺它时 Cwd=- ,相对命令按宿主进程 cwd 解析会静默起不来);启动器新增 --profile 档位(工作区 ~/.deta/<产品>/workspace、工具面缺省 full),运行时按 DETA_SERVER_ROOT → ~/.deta/runtime → 开发检出解析,入口优先打包产物;DETA_TOKEN 可选注入(缺省时云类工具返回 auth_required)。原远程端点声明(含 OAuth/401 段落)从插件移除。

文档与治理:根 README 与两个插件 README 改为单一管道口径;技能 aml-design 对齐本机全量面;新增 scripts/check-plugin-contract.mjs(E1 禁工具清单 / E2 必须给出 list_capabilities / E3 禁解释内部实现 / E4 市场条目一致性 / W1 开发检出依赖)与 .gitea/workflows/ci.yml。版本:studio 0.3.1、writer 0.1.0。
2026-09-20 11:56:23 +08:00

200 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: aml-design
description: 以 AML 为唯一事实源读写建筑模型并编译校验。当用户要求创建/修改建筑方案、房间布局、层高、开洞、围护结构或做建筑性能相关的模型准备时使用。
---
# DETA 建筑性能设计(AML)
## ★ 先读:工具怎么找、模型怎么改(任意工作目录都适用)
**工具发现规则(重要)**:宿主对插件类 MCP 工具做**懒加载检索**,一次检索只返回少量结果
(实测 `Only 10 shown of 23`)。**搜不到不等于不存在**——不确定有哪些工具时,先调
**`list_capabilities`**(能力目录)拿到当前形态的**完整工具名清单**,再按名字**直接调用**。
**改建筑模型只有一个标准动作**(能力目录里有 `build_model` 时):
`build_model({ aml, projectId })` —— 写服务端工作区 → 编译成建筑模型 → 规范校验 → 写进云项目,
一次调用完成;返回 `gate`(校验是否通过)、编译摘要、校验明细、云工作区 `headSha`。
- **不要**把 AML 拷进 Studio 的代码编辑器手工点编译(那是没有闭环工具时的兜底,不是正常路径);
- **不要**用脚本自绘模型图代替 Studio;
- 校验不通过(`gate: failed`)就按 `validation` 明细改 AML 后重跑,直到通过;
- 冲突(`version_conflict`)说明云工作区被其它会话改过:确认要覆盖才传 `force: true`。
**看模型 / 打开 Studio**:`open_studio` 拿一次性免密链接,再用宿主内置浏览器(`iab`)打开——
不要手工在面板登录,也不要用 playwright 逐步点击。
**执行器在线是模拟类工具的前置条件**:`simulate` / `studio_command` / `query_simulation_db` /
`view_canvas` 的算力在 ant-model 浏览器里的执行器,经网关 host-call 中继干活;项目标签页一关
就离线,工具会 fail fast 报「执行器离线」。`open_studio` 会回报 `executor_online`,遇到离线提示
就再调一次它,不要改用手工登录。
## 何时使用
用户提到建筑方案、房间/空间布局、层高、墙体开洞(门窗)、围护结构、体形系数、
建筑模型校验,或需要为后续能耗/日照/CFD 模拟准备模型时使用本技能。
## 编辑与校验分工(先搞清"哪份文件是真值")
本插件挂的是**本机 MCP**:引擎工作区才是编译/校验/模拟读的真值(启动器 stderr 会回显路径)。
两种用法:
- **工作区 = 项目目录**(启动宿主前设 `DETA_WORKSPACE=<项目目录>`):宿主原生文件工具与 MCP
工作区工具看的是同一份文件,直接改完就能编译,不需要同步步骤。
- **工作区 ≠ 项目目录**(缺省 `~/.deta/workspace`):本地改动要先同步进引擎工作区,
引擎工具读到的才是最新版本。
编辑手段按场景选:纯文本改动优先用宿主原生文件工具(read / patch / grep);需要按元素定向
读写 AML(按空间 ID 改属性、只取某实体块原文)时用 MCP 的工作区工具。编译、规范校验、
规则检查、围护结构统计、空间邻接一律走引擎工具。
当前形态到底有哪些工具、叫什么名字,以运行时调 `list_capabilities` 的结果为准。
| 要做的事 | 用什么 |
|----------|--------|
| 读取 / 修改 / 搜索 AML 与其它设计源文件(`aml.xml`、`bss.md`、`rules.yml`、`behaviors.yml`、`design-brief.md`) | **宿主原生工具**:read / patch / grep / shell(直接改文件,不走 MCP 编辑工具) |
| 云端编译(AML → building.json) | MCP `apply_design` |
| **改模型并让它出现在云项目/Studio(闭环单入口)** | **MCP `build_model`**(写工作区 → 编译 → 校验 → 云同步,一次调用完成) |
| 语法与几何校验 / 规则检查 | MCP `validate_model`(`checks` 一次要齐几何 + issues + rules,三类共用同一次编译) |
| 围护结构统计 | MCP `envelope_stats` |
| 空间邻接、交通空间合并 | MCP `query_spatial_graph`、`apply_design(merge_traffic_spaces=…)` |
| 领域脚本(面积预算 / 轴网 / 布局建议 / 校核) | MCP `run_script`、`run_scripts` |
| 把本地改动送上云端、取回云端工作区 | MCP `push_project`、`pull_project` |
| 语法规则与生成上下文 | MCP `get_aml_schema`、`generate_aml` |
固定顺序(工具面里有 `build_model` 时):**本地写 AML → `build_model` → 看 gate →(Studio 里看效果)**。
`build_model` 一次完成「写服务端工作区 → 编译 → 校验 → 写进云项目工作区」,Studio 里立即可见。
工具面里没有 `build_model`(部分部署形态会裁掉它)时才退化为:本地编辑 → `push_project` → `apply_design` →
`validate_model` → Studio 查看。引擎工具读的是**服务端工作区**的文件,没推送过就读不到你的最新改动。
**工具检索结果条数有限**:一次搜索没看到某个工具,不代表它不存在——先调
`list_capabilities` 拿当前形态的完整工具名,再按名字直接调用。
### 闭环单入口 build_model
```
build_model({ aml?: "<AML 全文>", files?: { "aml.xml": "…" }, projectId?: "24", force?: false })
```
- `aml` 给出则先写入引擎工作区 `aml.xml`;`files` 可一并写其它工作区文件(路径规则同 `push_project`)。
- `projectId` 缺省取工作区 `deta.json` 绑定的云项目;没有绑定就先
`push_project({ files, projectId })` 绑一次。
- 返回:`gate`(`passed` / `failed`)、编译摘要、校验明细、`cloud.headSha`、`studioUrl`。
- `gate: failed` → 按 warning/error 改 AML,再调一次 `build_model`,直到 `passed`。
- `status: conflict`(`version_conflict`)→ 云项目工作区被其它会话改过(例如 Studio 面板里编辑过),
确认要覆盖再传 `force: true` 重跑一次。
- `status: unavailable` → 当前没有云同步通道(未注入云令牌,或该部署形态未接云),改用
`apply_design` + `validate_model`(编译校验不依赖云)。
- **禁止**把 AML 拷进 Studio 的代码编辑器手工点编译:那是没有闭环工具时的兜底,不是正常路径。
### push 与 Studio 深链
- 需要云端校验、或想在 Studio 里看效果时,先
`push_project({ files: { "aml.xml": "<全文>", "rules.yml": "…" }, projectId?: "…" })`。
`files` 至少含 `aml.xml`;路径必须是工作区相对路径(绝对路径、`..` 穿越会被拒绝);
单次载荷上限 1 MiB。传 `projectId` 会同时把本项目绑定到云项目
(写入服务端工作区 `deta.json`,之后 `generate_aml` / `pull_project` 也带同一深链)。
- 返回的 `studioUrl`(`https://deta.city/design/<projectId>`,例:云项目 11 → `https://deta.city/design/11`):
**在宿主右侧的内置浏览器面板打开**(做法见下一节);已有相同 URL 的标签优先复用,不要重复开新标签。
- 反向核对 / 拉回云端工作区用 `pull_project`(返回 `{ files, projectId?, studioUrl? }`,
工作区为空时 `files` 为 `{}`)。
## 在右侧面板打开 Studio,并在其中跑模拟
Studio 就是deta.city 上的建筑性能应用。在 Codex 右侧内置浏览器面板打开它之后,
看模型、跑模拟、看结果图层都在面板里完成;本插件的 MCP 只负责把本地改动推上去,不执行模拟。
打开步骤(用宿主内置浏览器 = browser 插件的 `iab`):
1. **先调 `open_studio` 拿链接并确认执行器上线**(免手工登录)。返回 `url`
(`https://deta.city/mcp-api/portal-session/landing?ticket=…&next=/design/<id>`)、
`studioUrl`、`executor_online`、`expiresInSeconds`(180)。该链接在面板内会自动完成
deta.city 登录并跳到 Studio。
- 典型节奏:`open_studio()` 拿 `url` → 面板打开 → `open_studio({ waitSeconds: 20 })`
确认 `executor_online: true` → 再调 `simulate` / `studio_command` 等执行器侧工具。
- 若返回 `auth_required` → 先让用户完成 MCP 授权(`codex mcp login deta_mcp`)再重试;
若 `url` 报「票据无效或已过期」→ 重新调一次,不要改成手工登录。
2. 按 browser 插件技能(`control-in-app-browser`)的 Bootstrap 初始化,再取内置浏览器句柄:
`const iab = await agent.browsers.get("iab");`,并先读一次 `await iab.documentation()`。
3. 先 `await iab.tabs.list()` 看是否已有该 URL 的标签:**有就复用,不要调 `goto` 重载**
(重载会丢面板里正在进行的操作);没有才 `const tab = await iab.tabs.new(); await tab.goto(url);`
4. 打开后告诉用户「Studio 已在右侧面板打开(项目名/ID)」,并说明模拟在面板里运行。
旧路径(工具面里没有 `open_studio` 时):自己拼 `studioUrl`
(本机项目目录 `deta.json` 的 `projectId`,或 `push_project(…, projectId)` 的返回值,
形如 `https://deta.city/design/<projectId>`),按上面第 2–4 步打开——但需面板已登录。
在面板里跑模拟:
- 模拟入口在 Studio 界面内(分析/模拟面板、GH 模板等)。**默认交给用户在面板里操作**——
模拟参数与结果解读属设计决策,不要代替用户点。
- 用户明确要你代跑时:先 `await tab.ax.write()` 取当前界面元素,再 `await tab.ax.click(<元素序号>)`
逐步操作;每一步后重新取一次状态确认,**不要凭记忆点坐标**。
- 结果出来后用 `await tab.ax.write("both")` 或 `await tab.screenshot()` 确认图层与数值,再向用户汇报。
前置与故障:
- 面板未登录 deta.city:用 `open_studio` 的一次性链接即可免手工登录(见上);只有拿不到
`open_studio` 时才退化为手工:在面板里打开 `https://deta.city/login` 完成一次登录
(登录态写入该浏览器的 `ant_token` cookie 与 `ant-model-auth` localStorage,之后长期有效),
登录完成后重新打开 `studioUrl` 即自动加载项目。
- **宿主把 MCP 授权页开在哪个浏览器由宿主决定**(实测 Codex Desktop 走系统默认浏览器),
且**那一页的登录态不会进入面板**——所以别把"MCP 已授权"当成"面板已登录",两者要分别确认:
MCP 授权只解决 Codex↔服务端;面板登录解决 Studio 在面板里的会话(`open_studio` 正是两者的桥)。
实测口径:授权页在系统浏览器完成换码后停留在宿主的回调页("Authentication complete. You may close
this window."),该页不归我们控制;授权页自身已改为**在隐藏框架内完成换码**并给出「打开 deta.city」
与「关闭本页」,不再顶层跳走。
- 没有 `projectId`:Studio 打开的是空项目。先在门户创建云项目拿到 ID,再 `push_project(…, projectId)` 绑定。
- 宿主没有内置浏览器(CLI 等形态):直接把 `studioUrl` 给用户,让他自己打开,不要假装已经打开。
## 铁律
1. **AML 是建筑语义的唯一事实源**。任何几何或属性变更都必须落到 AML 文本,
不得用中间 JSON 表达修改意图。
2. **禁止凭记忆编写 AML 结构**。动手前必须先取真实语法:
- 已有模型:读工作区里的 `aml.xml`(宿主原生 read 工具,或 MCP 的 `read_source`)
- 语法规则:`get_aml_schema`(从编译服务实时获取,唯一权威)
3. **属性知识不硬编码**:房间用途、构造材料、洞口参数等可选值从工具返回中获取,
不要凭经验列举。
4. **局部修改优于整体重写**:改单个空间属性时只改该空间,不重写整个模型。
5. **控制单会话工具调用量**。编码代理在会话累积较多本插件工具调用后,会在请求里重复
声明 `deta` 命名空间,上游模型服务(Responses 兼容层)直接拒绝:
`Duplicate namespace name 'deta'; Namespace names must be unique`。
实测触发点随会话长度前移(并发调用会显著提前触发)。规程:
- 同一轮只调用一个本插件工具,不要并发;
- 单会话保持轻量,完成任务后另起会话继续;
- 一旦出现该错误,**停止重试并告知用户重开会话**(工作区文件不会丢失)。
6. **复杂形体(`<solid script="geometry/xxx.py">`)的脚本属于工作区文件,不是宿主本地文件**。
编译服务没有工作区访问权:编译前引擎会按 AML 声明的相对路径把脚本内容**随请求携带**
(键名必须与 AML 一字不差,含 `geometry/` 前缀)。因此:
- 脚本必须真实存在于**工作区**(用工作区文件工具读写,如 `geometry/shapes.py`);
- 脚本取不到时编译会**显式失败并列出原因**(而不是"编译通过但形体丢失");
- 改动脚本内容后无需重命名或改 AML;若 AML 里写了 `version="sha256:…"`,脚本内容变了
必须同步更新该版本号,否则编译报「几何脚本版本不匹配」。
## 标准工作流
1. **读**:用宿主原生工具读本地项目里的设计源码(`aml.xml` 等)。模型为空时先用
`generate_aml` 取生成上下文,再用 `get_aml_schema` 核对语法,然后在本地写出 AML。
2. **改**:在本地用 read / patch / grep 直接改 AML 文本(局部修改优于整体重写)。
3. **推**:`push_project({ files: { "aml.xml": … } })` 把改好的源码送到服务端工作区
(要绑云项目就带上 `projectId`)。
4. **编**:`apply_design` 提交编译 → 编译为建筑模型,产物落盘 `building.json`。
5. **校**:`validate_model` 做语法与规则校验,逐条读取错误码并修复,不得跳过;
规则类问题用 `validate_model({ checks: ['issues','rules'] })` 一次查齐(info 级提示只在 issues 视图可见)。
6. **看**:需要几何指标用 `envelope_stats`(围护结构/外窗面积)或 `query_spatial_graph`
(空间邻接与查询);要看模型、**跑模拟**、看结果图层,就在右侧面板打开 `studioUrl`
(见「在右侧面板打开 Studio,并在其中跑模拟」一节),模拟在 Studio 界面里运行。
## 错误处理
- 编译服务未在线时,编译/校验类工具会返回明确错误文本。此时**不要伪造结果**,
直接报告「编译服务未接入」,改用宿主原生文件工具(read / patch)核对与编辑本地 AML。
- 编译报错必须逐条修复后重新 `apply_design`,禁止在报错状态下声称完成。
## 工具名从哪来
本技能**不列工具清单**:工具面随部署形态(引擎形态 / 全量形态)裁剪,任何手写清单都会过期。
不确定有哪些工具时,调 `list_capabilities` 拿当前形态的**完整工具名**,再按名字直接调用;
每个工具能做什么、参数怎么给,以它自身的 description 与返回为准。