Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@ user-facing notes live in [`docs/updates/`](docs/updates/) (English and

## Unreleased

## 2.2.3 — 2026-10-14

### Added

- Editor: `sca cell ls|get|put|insert|rm|run` edits the open notebook's cells through the
running editor (found by `<workspace>/.sca-editor/server.json`): the page shows the change live,
with no reload, the cell runs, and the command prints its status, errors and output. `sca new
NAME [--kind part|assembly]` writes a notebook the editor then lists, leaving the person's view
alone. The routes behind them are `GET /api/cells` and `POST /api/cells/{edit,insert,delete,run}`.
- Editor: a change to the open notebook's file made by someone else (an agent) is noticed
within a second and applied cell by cell (edited cells are updated and run again, added or
removed cells appear or go), without a reload; a changed setup or `@app.function` cell restarts
the kernel. Notebooks added to or removed from the workspace appear in the list by themselves.

### Fixed

- Editor: an edit made in the editor no longer writes over what an agent saved to the same
notebook file. If a cell was edited in both places, the file's version is kept and the
editor's unsaved text goes to the log.

## 2.2.2 — 2026-10-14

### Added
Expand Down
26 changes: 12 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,23 +149,20 @@ the full crank cycle sweeps clean in the same sim ·

---

## Update Notes (2.2.2)
## Update Notes (2.2.3)

> Validate generated definitions, assembly constraints, and manufacturing
> geometry before production use.

- **Code completion from the SDK.** In the editor, `scad.` (and `scad.ql.`,
`scad.std.gear.`) lists the real functions with their signatures and
docstrings. Accepting one, or typing `(` after its name, writes the call with
every required parameter as `name=`, and Tab moves between them; inside a call
the parameters not given yet complete as `name=`.
- **New notebooks from the workspace tab.** A **new** action starts a part, or
an assembly that uses the first two parts, from the SDK's template; an empty
workspace opens on that form.
- **Fix.** The cell editors no longer rebuild their configuration on every
render, which dropped a snippet in progress.

Full notes for this version: [`docs/updates/2.2.2.md`](docs/updates/2.2.2.md).
- **The editor takes in edits made to the notebook file.** An agent's saved change is applied
cell by cell (changed cells update and run again, no reload), and is no longer written over by
the editor. If a cell was edited in both places, the file's version is kept and your unsaved
text goes to the log. Notebooks added to the workspace appear in the list by themselves.
- **`sca cell` and `sca new`.** `sca cell ls|get|put|insert|rm|run` edits the open notebook's cells
through the running editor (the page updates live, each write prints the cell's status and
errors); `sca new NAME` creates a notebook the editor then lists.

Full notes for this version: [`docs/updates/2.2.3.md`](docs/updates/2.2.3.md).
Earlier versions: the [changelog](CHANGELOG.md) and [`docs/updates/`](docs/updates/).

---
Expand All @@ -186,7 +183,7 @@ in a compact public API for creating solids, applying features, tagging semantic
intent, querying topology, exporting manufacturing files, and translating recorded
models into FreeCAD workflows.

Current release: `simplecadapi==2.2.2`.
Current release: `simplecadapi==2.2.3`.

## What It Provides

Expand Down Expand Up @@ -701,6 +698,7 @@ and the [STEP reconstruction workflow](docs/skill/references/workflows/step-reco

## Documentation

- 2.2.3 update notes: [`docs/updates/2.2.3.md`](docs/updates/2.2.3.md)
- 2.2.2 update notes: [`docs/updates/2.2.2.md`](docs/updates/2.2.2.md)
- 2.2.1 update notes: [`docs/updates/2.2.1.md`](docs/updates/2.2.1.md)
- 2.1.3b1 update notes: [`docs/updates/2.1.3b1.md`](docs/updates/2.1.3b1.md)
Expand Down
19 changes: 10 additions & 9 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,18 @@ CalculiX 静力 FEM(边界面按保真的 `interface.*` 标签选取,仿真

---

## 更新日志(2.2.2)
## 更新日志(2.2.3)

> 投入生产前请验证生成的定义、装配约束和制造几何。

- **来自 SDK 的代码补全。** 在编辑器里,输入 `scad.`(以及 `scad.ql.`、`scad.std.gear.`)
会列出真实存在的函数、签名和文档说明。选中一个函数,或在函数名后输入 `(`,会把每个必填
参数写成 `name=`,Tab 在它们之间跳转;在调用括号内,还没写的参数会补全成 `name=`。
- **在工作区页面创建 notebook。** 新增的 **new** 按 SDK 模板创建一个零件,或一个使用前两个
零件的装配;空工作区会直接打开这个表单。
- **修复。** cell 编辑器不再每次渲染都重建配置,这会让进行中的占位跳转丢失。
- **编辑器会接收对 notebook 文件的修改。** agent 保存的修改会按 cell 逐个应用(变化的 cell 更新并重新运行,
不刷新页面),不再被编辑器覆盖。同一个 cell 两边都改时,保留文件里的版本,你未保存的文字记入日志。
工作区里新增的 notebook 会自动出现在列表中。
- **`sca cell` 和 `sca new`。** `sca cell ls|get|put|insert|rm|run` 通过运行中的编辑器修改打开的
notebook 的 cell(页面实时更新,每次写入都打印该 cell 的状态和错误);`sca new NAME` 创建一个
编辑器随即列出的 notebook。

本版本的完整说明:[`docs/updates/2.2.2.zh-CN.md`](docs/updates/2.2.2.zh-CN.md)。
本版本的完整说明:[`docs/updates/2.2.3.zh-CN.md`](docs/updates/2.2.3.zh-CN.md)。
更早的版本:见[更新日志](CHANGELOG.md)和 [`docs/updates/`](docs/updates/)。

---
Expand All @@ -162,7 +162,7 @@ CalculiX 静力 FEM(边界面按保真的 `interface.*` 标签选取,仿真

SimpleCADAPI 是一个基于 OCP 的 Python CAD SDK,提供清晰的函数式建模操作和可重放的模型图。它在 OpenCascade 几何内核之上提供精简的公共 API,可用于创建实体、应用特征、添加语义标签、查询拓扑、导出制造文件,以及将记录的模型转换为 FreeCAD 工作流。

当前版本:`simplecadapi==2.2.2`。
当前版本:`simplecadapi==2.2.3`。

## 核心能力

Expand Down Expand Up @@ -588,6 +588,7 @@ uv run --extra fem python examples/ap242_gmsh_volume_mesh/run_calculix.py

## 文档

- 2.2.3 更新说明:[`docs/updates/2.2.3.zh-CN.md`](docs/updates/2.2.3.zh-CN.md)
- 2.2.2 更新说明:[`docs/updates/2.2.2.zh-CN.md`](docs/updates/2.2.2.zh-CN.md)
- 2.2.1 更新说明:[`docs/updates/2.2.1.zh-CN.md`](docs/updates/2.2.1.zh-CN.md)
- 2.1.3b1 更新说明:[`docs/updates/2.1.3b1.zh-CN.md`](docs/updates/2.1.3b1.zh-CN.md)
Expand Down
3 changes: 3 additions & 0 deletions docs/landing.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ each instruction to one action and wait for them.
these edges by 1 mm"). You read the selection from the file (`selection` cell) or with
`sca snapshot`, and you can look at `.sca-editor/viewport.png` to see what they see. Then
you edit the notebook; they see your change in the editor.
- **Work through the editor.** Change cells with `sca cell` (`sca cell ls`, `put`, `insert`):
the page updates live and nothing the person typed is overwritten. Editing the file works
too: the editor takes the change in within a second.
- **"Change this cell."** Every cell has a copy button that copies a reference such as
`/path/u_link.py:L47-L48 (cell 02 ...)`. They paste it to you with what they want changed,
and you edit exactly those lines.
Expand Down
10 changes: 6 additions & 4 deletions docs/skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ description: Build, assemble, inspect, reconstruct, and export parametric CAD mo
license: Apache-2.0
metadata:
project: simplecadapi
version: 2.2.2
version: 2.2.3
package-name: simplecadapi
package-version: 2.2.2
package-version: 2.2.3
---

# SimpleCAD SDK Skill
Expand Down Expand Up @@ -50,7 +50,9 @@ Paths are relative to this file's directory.
selected, and you MUST read
`references/domains/editor-collaboration.md` first to see what they
see (selection cell, `sca snapshot`, cell references) and how to
hand the work back.
hand the work back. While the editor runs, change its notebooks with
`sca cell` (or the file; never both blindly): the editor is the
file's writer.
- Creating, installing, updating, or removing a SimpleCADAPI addon (a
third-party skill+tooling package around `.scadpkg`) enters no
workflow; you MUST use `references/domains/addon-development.md`
Expand Down Expand Up @@ -202,7 +204,7 @@ print(len(rebuilt))
- `references/inspect/brep-reverse-engineering.md`
- `references/domains/addon-development.md` — `sca` addon CLI and authoring guide
- `references/domains/editor-collaboration.md` — working with a person in `sca edit`:
selection cell, snapshot, cell references, parameters
selection cell, snapshot, cell references, `sca cell` / `sca new`, parameters
- `references/docs/guides/reconstruction-agent-test-prompt.md`
- `references/docs/guides/reconstruction-agent-strategy.md`
- `references/docs/guides/notebook-runtime.md`
Expand Down
48 changes: 44 additions & 4 deletions docs/skill/references/domains/editor-collaboration.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,26 @@ edit code. It is not a workflow. The modeling you do still follows the workflow
you selected; this page says how to see what the person sees and how to hand
work back.

The notebook file is the only shared state. The editor autosaves every edit to
The notebook file is the shared state. The editor autosaves every edit to
it, and every message the person gives you (a selection, a cell reference, a
tuned value) is also something you can read from disk. Never rely on what the
person says they selected when the file or the snapshot can tell you.

The editor holds the open notebook in memory and is the one writer of its
file. You have two safe ways to change it while it runs; use the first:

1. **`sca cell` (preferred).** It edits through the editor: the page shows the
change live (no reload, no flicker), the cell runs, and you get its state back.
2. **Edit the file.** The editor notices a saved change within a second, compares
it with its cells and applies only what differs (changed cells are edited in
place and run again, added or removed cells appear or go away). A change to the
setup cell or an `@app.function` cell restarts the kernel instead. A file that
does not parse is ignored until the next save that does.

If the person has the same cell open with unsaved typing, **your version wins**:
their text is dropped and kept in the editor's log for them. Do not rewrite a
cell the person is typing in without telling them.

## Start the editor for a person

```bash
Expand All @@ -28,6 +43,29 @@ sca edit <workspace> --no-browser --port 7180
the assembly that fixes them together) to `./u_link_motor_mount`, then
`sca edit ./u_link_motor_mount`.

## Edit cells through the editor: `sca cell`

```bash
sca cell ls [--code] # numbered cells with status, errors and output
sca cell get 3 # one cell: code, status, errors, output
echo 'L = 90' | sca cell put 3 # replace the code of cell 3 and run it (--no-run to only save)
sca cell insert --after 3 -f new.py # add a cell (--after start|end|CELL, --name fn_name)
sca cell rm 4
sca cell run [CELL ...] # run cells (default all) and what they feed
sca new bracket --kind part # a new notebook; the open editor lists it, the person's view stays
```

- A cell is named by its number in `sca cell ls`, its `key`, its function name, or its id.
Numbers move when cells are added or removed: read the list the command prints back.
- Each write prints the touched cell's state (`status`, `errors`, `output`). That is the
feedback: read it before the next step, as with any other operation.
- `put` fails with a conflict if you pass a base that is out of date; without one it
replaces the cell, so `get` first when the person may have changed it.
- The commands find the running editor through `<workspace>/.sca-editor/server.json`. With no
editor running, or with another notebook open, `ls` and `get` read the file and the write
commands refuse: then edit the file directly, nothing else holds it.
- `@app.function` cells cannot be changed this way; edit them in the file.

## Read what the person is doing

| Need | Where |
Expand Down Expand Up @@ -140,10 +178,12 @@ file first, since every cell is blocked until it compiles.

## Rules of thumb

- Re-read the file before editing: the person edits and autosaves too, and the
editor rewrites the selection cell.
- Edit by cell. A change that touches many cells at once makes the person's
- Re-read the cell before editing (`sca cell get`, or the file): the person edits and
autosaves too, and the editor rewrites the selection cell.
- Edit by cell, with `sca cell`. A change that touches many cells at once makes the person's
screen reflow and loses their place.
- New notebooks: `sca new`, not a bare file write plus a request to refresh; the editor
lists a new file by itself either way.
- After an edit, say which cells you changed (by reference) and what to look
at, so the person can run them and judge the result.
- Never edit `__marimo__/` or `.sca-editor/`; both are generated.
Expand Down
37 changes: 37 additions & 0 deletions docs/updates/2.2.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 2.2.3 Update Notes

The editor (`sca edit`) and an agent can now work on the same notebook without overwriting each other.

## The editor takes in edits made to the file

Before, the editor held the open notebook in memory and rewrote the file on each edit, so a change
an agent saved was overwritten by the editor's next save and never shown. Now the file is watched:
a saved change is compared with the editor's cells and applied cell by cell. Changed cells are
updated and run again, added or removed cells appear or go away, and the page does not reload or
flicker. A change to the setup cell or an `@app.function` cell restarts the kernel instead; a file
that does not parse is ignored until the next save that does.

If a cell was edited in both places, **the file's version is kept** and the text you had not saved
goes to the log at the bottom. Notebooks added to or removed from the workspace appear in the list
by themselves.

## `sca cell` and `sca new`

```bash
sca cell ls [--code] # numbered cells with status, errors and output
sca cell get 3
echo 'L = 90' | sca cell put 3 # replace a cell's code and run it
sca cell insert --after 3 -f new.py
sca cell rm 4
sca cell run [CELL ...]
sca new bracket --kind part # a new notebook, listed by the running editor
```

These go through the running editor, found by `<workspace>/.sca-editor/server.json`: the page shows
the change live and each write prints the touched cell's status, errors and output. With no editor
running, or another notebook open, `ls` and `get` read the file and the write commands refuse: edit
the file directly then.

The skill (`editor-collaboration`) and `landing.md` now tell agents to work this way.

See the [changelog](../../CHANGELOG.md) for the complete list.
33 changes: 33 additions & 0 deletions docs/updates/2.2.3.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# 2.2.3 更新说明

`sca edit` 编辑器和 agent 现在可以同时处理同一个 notebook,互不覆盖。

## 编辑器会接收对文件的修改

以前编辑器把打开的 notebook 放在内存里,每次编辑都重写文件,agent 保存的修改会被编辑器的下一次保存
覆盖,也不会显示出来。现在编辑器会监视文件:保存后的修改会与编辑器里的 cell 对比,按 cell 逐个应用。
变化的 cell 会更新并重新运行,新增或删除的 cell 会出现或消失,页面不会刷新或闪烁。setup cell 或
`@app.function` cell 的修改会重启 kernel;无法解析的文件会被忽略,直到下一次可解析的保存。

如果同一个 cell 两边都改了,**保留文件里的版本**,你还没保存的文字会记在底部日志里。工作区里新增或删除的
notebook 会自动出现在列表中。

## `sca cell` 和 `sca new`

```bash
sca cell ls [--code] # 带编号的 cell,含状态、错误和输出
sca cell get 3
echo 'L = 90' | sca cell put 3 # 替换 cell 代码并运行
sca cell insert --after 3 -f new.py
sca cell rm 4
sca cell run [CELL ...]
sca new bracket --kind part # 新建 notebook,运行中的编辑器会列出它
```

这些命令通过运行中的编辑器工作(由 `<workspace>/.sca-editor/server.json` 找到):页面实时显示修改,每次写入
都会打印被改 cell 的状态、错误和输出。没有运行中的编辑器,或编辑器打开的是别的 notebook 时,`ls` 和 `get`
读取文件,写命令会拒绝:这时直接编辑文件即可。

skill(`editor-collaboration`)和 `landing.md` 已让 agent 按这种方式工作。

完整列表见[更新日志](../../CHANGELOG.md)。
13 changes: 13 additions & 0 deletions editor-web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,13 @@ export function App() {
setCells(next);
log.knowCells(next);
});
// A notebook was added or removed under the workspace (an agent wrote one).
socket.on("workspace.changed", () => refreshWorkspace());
// The server dropped an edit made on a cell that had changed on disk.
socket.on("cell.conflict", (envelope) => {
const mine = String(envelope["mine"] ?? "");
log.push("error", `a cell changed on disk while you were editing it: kept the file's version. Your unsaved text was:\n${mine.length > 600 ? `${mine.slice(0, 600)}…` : mine}`);
});
socket.on("notebook.features", (envelope) => setFeatures((envelope["features"] as NotebookFeature[]) ?? []));

socket.on("preview", (envelope) => {
Expand Down Expand Up @@ -355,6 +362,12 @@ export function App() {
socket={socketRef.current}
notebook={notebook}
onInterrupt={handleStop}
onConflict={(cell, mine) =>
log.push(
"error",
`${cell.title ?? "cell"} changed on disk while you were editing it: kept the file's version. Your unsaved text was:\n${mine.length > 600 ? `${mine.slice(0, 600)}…` : mine}`,
)
}
/>
</TabsContent>
<TabsContent value="workspace" className="min-h-0">
Expand Down
Loading
Loading