内容
# Ecky CAD
Prompt-driven CAD: 用文字描述一个零件,LLM 用小型建模语言编写它,并将其渲染为精确的 B-rep 立体模型,您可以读取、编辑和版本控制。
> 早期和预发布版本(v0.0.1)。预计会有粗糙的边缘和破坏性的变化。
## 工作原理
LLM 不会发出网格或脚本。它编写 `.ecky`,通过三个层次编译:
- **Surface** — 带括号的 Scheme:`(model (part ...))`。
- **Core IR** — 固定的操作集,Surface 层降低到:基本体、布尔运算、选择器、放置、重复。内核只看到这个集合。
- **Backend** — 默认情况下是本地 OCCT(B-rep,可选面和边)。build123d 和 FreeCAD 是后续后端,用于交叉检查和导入。
## 效果展示
一个参数化外壳:命名尺寸、带通风孔的空心主体、顶部边缘带有圆角、以及一个 `verify` 子句,用于将盖子间隙固定到一个要求。
```scheme
(model
(params
(number body_w 80 :label "主体宽度" :min 40 :max 120 :step 1)
(number body_d 50 :label "主体深度" :min 30 :max 90 :step 1)
(number body_h 20 :label "主体高度" :min 10 :max 40 :step 1)
(number wall 2 :label "壁厚" :min 1 :max 5 :step 0.5)
(number vent_r 3 :label "通风孔半径" :min 1 :max 6 :step 0.5))
; 盖子必须保持至少 0.3 毫米的间隙在主体上方
(verify
(tag lid_clearance body.lid_gap)
(metric gap (clearance min-distance body lid))
(expect gap (>= 0.3)))
(part body
(build
(shape hollow (shell wall :faces "top" (box body_w body_d body_h)))
(shape vent (translate 0 0 -0.5 (cylinder vent_r (+ body_h 1))))
(result
(fillet 1.5 :edges "top"
(difference hollow vent)))))
(part lid
(translate 0 0 (+ body_h 0.4)
(box (- body_w (* wall 2)) (- body_d (* wall 2)) 3))))
```
`params` 提升尺寸到标记的滑块。`build` 命名每个中间实体;`difference` 在空心主体中打通通风孔;`fillet` 将顶部边缘圆角化。`verify` 声明一个不变性 — 最小盖子间隙 — 由 `verify_generated_model` 检查,独立于当前渲染的几何图形。
更小的尺寸也适用 — `(model (part p (sphere 10)))` 可以独立渲染。 [Ecky IR 指南](docs/books/ecky-ir/index.md) 从这里开始,逐章构建。
## 功能
- 版本历史,保存在 SQLite 中。
- 在迭代之间,将视口截图反馈给 LLM。
- 将设计分支到新线程中。
- 手动编辑生成的 IR 并提交它。
- LLM:Gemini、OpenAI 兼容、Ollama。
- 用于外部代理的 MCP 服务器(检查 / 验证 / 预览 / 提交)。
## 入门指南
### 先决条件
- **Node.js** 和 **Rust** — 用于 Tauri/Svelte 应用程序。
- **Python 3.10+** — 用于互操作后端和运行时工具。
- **FreeCAD** (可选)— 仅需要用于 FreeCAD 互操作后端;`freecadcmd` 必须在您的 `PATH` 中。
本地 OCCT 内核和 build123d/speech 运行时由以下准备脚本在本地构建 — 您不需要系统 FreeCAD 作为默认后端。
### 安装和运行
```bash
# 1. 克隆,然后安装 JS 依赖
npm install
# 2. 构建本地 CAD 运行时(OCCT 内核,build123d,speech)
npm run runtimes:prepare
# 3. 在开发模式下启动桌面应用程序
npm run tauri dev
```
然后打开应用程序设置(⚙️)以选择 LLM 提供商并添加您的 API 密钥。开始输入您要构建的内容。
> 只需要网页前端而不需要桌面外壳?`npm run dev` 同时运行 Vite 前端和 Node 服务器端。
## 两种驱动方式
**API 模式。** Ecky 直接调用 LLM 提供商,生成 `.ecky` 文件,并根据您的提示创建模型。 在设置(⚙️)中选择提供商和模型。支持 Gemini、任何 OpenAI 兼容的端点和本地 Ollama。
**代理模式(MCP)。** 将外部编码代理指向 Ecky 的内置 MCP 服务器,它使用自己的工具编写模型,执行 `检查 → 验证 → 预览 → 提交`(`workspace_overview` 查看周围,`macro_preview_render` 预览 `.ecky` 源代码,`commit_preview_version` 持久化)。Ecky 可以为代理加载导出预制的 MCP 技能包。
使用以下命令测试 MCP 预览 → 提交路径:
```bash
npm run mcp:smoke -- <线程 ID> <路径到模型.ecky> [MCP URL]>
```
## 开发
完整的约定在 [AGENTS.md](AGENTS.md) 中。简要版本:
- **测试优先(BDD 双循环)。** 从失败的集成测试开始,通过单元测试驱动,红绿重构。在每个步骤后运行相关的测试套件。
- **约定提交。** `type(scope): description`;release-please 读取它们以计算版本和更改日志。
- **Tauri 边界。** 前端有效载荷为 `camelCase`,Rust 结构体为 `snake_case`;合约层进行转换。使用 `npm run generate:contracts` 重新生成 TS 绑定。
```bash
npm run test:unit # Svelte/TS 单元测试
npm run test:e2e # Playwright 端到端测试
npm run typecheck # svelte-check + tsc
cd src-tauri && cargo test # Rust 后端测试
```