agentcad-cli 0.1.2__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/PKG-INFO +2 -9
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/README.md +1 -8
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/pyproject.toml +1 -1
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/workspace/CLAUDE.md +0 -1
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/cli.py +7 -23
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad_cli.egg-info/PKG-INFO +2 -9
- agentcad_cli-0.1.3/tests/test_cli.py +164 -0
- agentcad_cli-0.1.2/tests/test_cli.py +0 -138
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/setup.cfg +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/__init__.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/__main__.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/__init__.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/model/README.md +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/model/design.json +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/model/params.json +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/model/part.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/workspace/cadproject.json +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/workspace/models/.gitkeep +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/workspace/references/build123d-guide.md +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/workspace/references/images/.gitkeep +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/workspace/references/notes.md +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/workspace/references/validation-strategy.md +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/checks/__init__.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/checks/mesh.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/checks/relations.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/checks/section.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/contract.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/geometry.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/inspect.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/jsonio.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/measure.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/payloads.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/precheck.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/probe.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/render.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/report.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/review.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/runner.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/section.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/stl.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/templates.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/validate.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/workspace.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad_cli.egg-info/SOURCES.txt +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad_cli.egg-info/dependency_links.txt +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad_cli.egg-info/entry_points.txt +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad_cli.egg-info/requires.txt +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad_cli.egg-info/top_level.txt +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_checks_relations.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_checks_section.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_deliver.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_geometry.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_jsonio.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_precheck_review.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_probe.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_render.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_runner.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_section.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_stale.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_stl.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_validate.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_weak_check.py +0 -0
- {agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/tests/test_workspace.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentcad-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Agent-first CAD workflow runtime
|
|
5
5
|
Author: AgentCAD contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -89,13 +89,6 @@ agentcad init --model demo
|
|
|
89
89
|
Then open this directory in Claude Code / Cursor and continue from
|
|
90
90
|
`models/demo/part.py`.
|
|
91
91
|
|
|
92
|
-
`--project` is optional. Use it only when you run commands outside the
|
|
93
|
-
workspace root, for example:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
agentcad init --model demo --project /tmp/agentcad-demo
|
|
97
|
-
```
|
|
98
|
-
|
|
99
92
|
For local development:
|
|
100
93
|
|
|
101
94
|
```bash
|
|
@@ -106,7 +99,7 @@ uv run agentcad --help
|
|
|
106
99
|
## Quick example
|
|
107
100
|
|
|
108
101
|
```bash
|
|
109
|
-
agentcad init --model bracket
|
|
102
|
+
agentcad init --model bracket
|
|
110
103
|
cd /tmp/my-cad-project
|
|
111
104
|
|
|
112
105
|
# 1. Design-time: solve the contract before writing geometry
|
|
@@ -77,13 +77,6 @@ agentcad init --model demo
|
|
|
77
77
|
Then open this directory in Claude Code / Cursor and continue from
|
|
78
78
|
`models/demo/part.py`.
|
|
79
79
|
|
|
80
|
-
`--project` is optional. Use it only when you run commands outside the
|
|
81
|
-
workspace root, for example:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
agentcad init --model demo --project /tmp/agentcad-demo
|
|
85
|
-
```
|
|
86
|
-
|
|
87
80
|
For local development:
|
|
88
81
|
|
|
89
82
|
```bash
|
|
@@ -94,7 +87,7 @@ uv run agentcad --help
|
|
|
94
87
|
## Quick example
|
|
95
88
|
|
|
96
89
|
```bash
|
|
97
|
-
agentcad init --model bracket
|
|
90
|
+
agentcad init --model bracket
|
|
98
91
|
cd /tmp/my-cad-project
|
|
99
92
|
|
|
100
93
|
# 1. Design-time: solve the contract before writing geometry
|
|
@@ -363,7 +363,6 @@ agentcad inspect <model> # Three-axis scan + section SVG
|
|
|
363
363
|
agentcad report <model> # Generate Markdown validation report
|
|
364
364
|
```
|
|
365
365
|
|
|
366
|
-
All commands accept `--project <dir>` (defaults to current directory).
|
|
367
366
|
All commands output machine-readable JSON by default.
|
|
368
367
|
|
|
369
368
|
### agentcad probe — Discover expected values before writing design.json
|
|
@@ -39,27 +39,23 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
39
39
|
parser.add_argument("--version", action="version", version=f"agentcad {__version__}")
|
|
40
40
|
sub = parser.add_subparsers(dest="command", required=True)
|
|
41
41
|
|
|
42
|
-
init = sub.add_parser("init", help="initialize a workspace
|
|
43
|
-
|
|
42
|
+
init = sub.add_parser("init", help="initialize a workspace and create first model")
|
|
43
|
+
init.add_argument("name", help="workspace name")
|
|
44
44
|
init.add_argument("--model", default=None, help="create an initial model after workspace initialization")
|
|
45
45
|
init.add_argument("--force", action="store_true")
|
|
46
46
|
|
|
47
47
|
new = sub.add_parser("new", help="create a new model (auto-initializes workspace)")
|
|
48
|
-
add_project_arg(new)
|
|
49
48
|
new.add_argument("model")
|
|
50
49
|
new.add_argument("--force", action="store_true")
|
|
51
50
|
|
|
52
51
|
build = sub.add_parser("build", help="build a model and export STEP/STL")
|
|
53
|
-
add_project_arg(build)
|
|
54
52
|
build.add_argument("model")
|
|
55
53
|
build.add_argument("--force", action="store_true", help="force rebuild even if source is unchanged")
|
|
56
54
|
|
|
57
55
|
measure = sub.add_parser("measure", help="measure generated STL geometry")
|
|
58
|
-
add_project_arg(measure)
|
|
59
56
|
measure.add_argument("model")
|
|
60
57
|
|
|
61
58
|
render = sub.add_parser("render", help="render an SVG preview from STL")
|
|
62
|
-
add_project_arg(render)
|
|
63
59
|
render.add_argument("model")
|
|
64
60
|
render.add_argument("--view", choices=["iso", "front", "top", "side", "back"], default="iso")
|
|
65
61
|
render.add_argument(
|
|
@@ -75,7 +71,6 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
75
71
|
help="render a Y cross-section SVG (XZ plane) at this position (mm)")
|
|
76
72
|
|
|
77
73
|
validate = sub.add_parser("validate", help="build, measure, render, and validate a model")
|
|
78
|
-
add_project_arg(validate)
|
|
79
74
|
validate.add_argument("model")
|
|
80
75
|
validate.add_argument("--view", choices=["iso", "front", "top", "side", "back"], default="iso")
|
|
81
76
|
validate.add_argument(
|
|
@@ -85,12 +80,10 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
85
80
|
)
|
|
86
81
|
|
|
87
82
|
deliver = sub.add_parser("deliver", help="write a delivery manifest")
|
|
88
|
-
add_project_arg(deliver)
|
|
89
83
|
deliver.add_argument("model")
|
|
90
84
|
deliver.add_argument("--no-validate", action="store_true")
|
|
91
85
|
|
|
92
86
|
probe = sub.add_parser("probe", help="probe STL cross-section to get geometry values for design.json")
|
|
93
|
-
add_project_arg(probe)
|
|
94
87
|
probe.add_argument("model")
|
|
95
88
|
probe.add_argument("--z", default=None, help="Z height(s) to probe, comma-separated")
|
|
96
89
|
probe.add_argument("--x", default=None, help="X position(s) to probe (YZ plane), comma-separated")
|
|
@@ -104,24 +97,19 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
104
97
|
probe.add_argument("--samples", type=int, default=20, help="number of scan samples (default: 20)")
|
|
105
98
|
|
|
106
99
|
report = sub.add_parser("report", help="generate a human-readable Markdown validation report")
|
|
107
|
-
add_project_arg(report)
|
|
108
100
|
report.add_argument("model")
|
|
109
101
|
|
|
110
102
|
inspect = sub.add_parser("inspect", help="three-axis scan + section SVGs + suggested probe commands")
|
|
111
|
-
add_project_arg(inspect)
|
|
112
103
|
inspect.add_argument("model")
|
|
113
104
|
inspect.add_argument("--samples", type=int, default=20, help="scan samples per axis (default: 20)")
|
|
114
105
|
|
|
115
106
|
precheck = sub.add_parser("precheck", help="solve design.json statically (before writing part.py)")
|
|
116
|
-
add_project_arg(precheck)
|
|
117
107
|
precheck.add_argument("model")
|
|
118
108
|
|
|
119
109
|
review = sub.add_parser("review", help="pre-delivery checklist + pairwise relations matrix")
|
|
120
|
-
add_project_arg(review)
|
|
121
110
|
review.add_argument("model")
|
|
122
111
|
|
|
123
112
|
sync = sub.add_parser("sync", help="update workspace scaffold files from templates")
|
|
124
|
-
add_project_arg(sync)
|
|
125
113
|
sync.add_argument("--dry-run", action="store_true", help="preview template updates without writing files")
|
|
126
114
|
sync.add_argument("--only", default=None, help="sync only one template path prefix (e.g. references/)")
|
|
127
115
|
sync.add_argument("--prune-deprecated", action="store_true", help="remove deprecated scaffold paths like skills/")
|
|
@@ -129,13 +117,9 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
129
117
|
return parser
|
|
130
118
|
|
|
131
119
|
|
|
132
|
-
def add_project_arg(parser: argparse.ArgumentParser) -> None:
|
|
133
|
-
parser.add_argument("--project", default=".", help="project directory, defaults to current directory")
|
|
134
|
-
|
|
135
|
-
|
|
136
120
|
def _resolve_project(args: argparse.Namespace) -> Path:
|
|
137
121
|
"""Find existing project, or auto-init when creating a new model."""
|
|
138
|
-
project = Path(
|
|
122
|
+
project = Path(".")
|
|
139
123
|
try:
|
|
140
124
|
return find_project(project)
|
|
141
125
|
except FileNotFoundError:
|
|
@@ -153,11 +137,11 @@ def _resolve_project(args: argparse.Namespace) -> Path:
|
|
|
153
137
|
|
|
154
138
|
def dispatch(args: argparse.Namespace) -> dict:
|
|
155
139
|
if args.command == "init":
|
|
156
|
-
|
|
140
|
+
workspace_name = str(getattr(args, "name"))
|
|
141
|
+
model_name = str(getattr(args, "model", "") or workspace_name)
|
|
142
|
+
target = (Path.cwd() / workspace_name).resolve()
|
|
143
|
+
|
|
157
144
|
init_payload = init_workspace(target, force=getattr(args, "force", False))
|
|
158
|
-
model_name = getattr(args, "model", None)
|
|
159
|
-
if not model_name:
|
|
160
|
-
return init_payload
|
|
161
145
|
model_payload = new_model(target, model_name, force=getattr(args, "force", False))
|
|
162
146
|
return {
|
|
163
147
|
"ok": bool(init_payload.get("ok")) and bool(model_payload.get("ok")),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentcad-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Agent-first CAD workflow runtime
|
|
5
5
|
Author: AgentCAD contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -89,13 +89,6 @@ agentcad init --model demo
|
|
|
89
89
|
Then open this directory in Claude Code / Cursor and continue from
|
|
90
90
|
`models/demo/part.py`.
|
|
91
91
|
|
|
92
|
-
`--project` is optional. Use it only when you run commands outside the
|
|
93
|
-
workspace root, for example:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
agentcad init --model demo --project /tmp/agentcad-demo
|
|
97
|
-
```
|
|
98
|
-
|
|
99
92
|
For local development:
|
|
100
93
|
|
|
101
94
|
```bash
|
|
@@ -106,7 +99,7 @@ uv run agentcad --help
|
|
|
106
99
|
## Quick example
|
|
107
100
|
|
|
108
101
|
```bash
|
|
109
|
-
agentcad init --model bracket
|
|
102
|
+
agentcad init --model bracket
|
|
110
103
|
cd /tmp/my-cad-project
|
|
111
104
|
|
|
112
105
|
# 1. Design-time: solve the contract before writing geometry
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Tests for CLI dispatch and auto-init behavior."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import agentcad.cli as cli_mod
|
|
8
|
+
from agentcad.cli import main
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_new_auto_init(tmp_path, monkeypatch):
|
|
12
|
+
monkeypatch.chdir(tmp_path)
|
|
13
|
+
result = main(["new", "bracket"])
|
|
14
|
+
assert result == 0
|
|
15
|
+
assert (tmp_path / "bracket" / "cadproject.json").exists()
|
|
16
|
+
assert (tmp_path / "bracket" / "CLAUDE.md").exists()
|
|
17
|
+
assert (tmp_path / "bracket" / "models" / "bracket" / "part.py").exists()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_init_creates_workspace_and_optional_model(tmp_path, monkeypatch):
|
|
21
|
+
monkeypatch.chdir(tmp_path)
|
|
22
|
+
result = main(["init", "initproj", "--model", "demo"])
|
|
23
|
+
assert result == 0
|
|
24
|
+
project = tmp_path / "initproj"
|
|
25
|
+
assert (project / "cadproject.json").exists()
|
|
26
|
+
assert (project / "models" / "demo" / "part.py").exists()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_init_default_creates_project_dir_named_after_model(tmp_path, monkeypatch):
|
|
30
|
+
monkeypatch.chdir(tmp_path)
|
|
31
|
+
result = main(["init", "fan8025"])
|
|
32
|
+
assert result == 0
|
|
33
|
+
assert (tmp_path / "fan8025" / "cadproject.json").exists()
|
|
34
|
+
assert (tmp_path / "fan8025" / "models" / "fan8025" / "part.py").exists()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_init_model_overrides_workspace_name_for_model(tmp_path, monkeypatch):
|
|
38
|
+
monkeypatch.chdir(tmp_path)
|
|
39
|
+
result = main(["init", "fan8025", "--model", "demo"])
|
|
40
|
+
assert result == 0
|
|
41
|
+
assert (tmp_path / "fan8025" / "cadproject.json").exists()
|
|
42
|
+
assert (tmp_path / "fan8025" / "models" / "demo" / "part.py").exists()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_new_default_creates_project_dir_named_after_model(tmp_path, monkeypatch):
|
|
46
|
+
monkeypatch.chdir(tmp_path)
|
|
47
|
+
result = main(["new", "fan8025"])
|
|
48
|
+
assert result == 0
|
|
49
|
+
assert (tmp_path / "fan8025" / "cadproject.json").exists()
|
|
50
|
+
assert (tmp_path / "fan8025" / "models" / "fan8025" / "part.py").exists()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_new_duplicate_fails(tmp_path, monkeypatch):
|
|
54
|
+
monkeypatch.chdir(tmp_path)
|
|
55
|
+
main(["new", "bracket"])
|
|
56
|
+
result = main(["new", "bracket"])
|
|
57
|
+
assert result == 1
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_new_duplicate_force(tmp_path, monkeypatch):
|
|
61
|
+
monkeypatch.chdir(tmp_path)
|
|
62
|
+
main(["new", "bracket"])
|
|
63
|
+
result = main(["new", "bracket", "--force"])
|
|
64
|
+
assert result == 0
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_build_missing_model(tmp_path, monkeypatch):
|
|
68
|
+
monkeypatch.chdir(tmp_path)
|
|
69
|
+
main(["new", "bracket"])
|
|
70
|
+
result = main(["build", "nonexistent"])
|
|
71
|
+
assert result == 1
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_validate_default_model(tmp_path, monkeypatch):
|
|
75
|
+
"""Validate the default scaffold model (should build and validate ok)."""
|
|
76
|
+
monkeypatch.chdir(tmp_path)
|
|
77
|
+
main(["new", "test_block"])
|
|
78
|
+
monkeypatch.chdir(tmp_path / "test_block")
|
|
79
|
+
result = main(["validate", "test_block"])
|
|
80
|
+
assert result == 0
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_version():
|
|
84
|
+
import pytest
|
|
85
|
+
with pytest.raises(SystemExit) as exc_info:
|
|
86
|
+
main(["--version"])
|
|
87
|
+
assert exc_info.value.code == 0
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_sync_updates_workspace(tmp_path, monkeypatch):
|
|
91
|
+
monkeypatch.chdir(tmp_path)
|
|
92
|
+
main(["new", "bracket"])
|
|
93
|
+
project = tmp_path / "bracket"
|
|
94
|
+
monkeypatch.chdir(project)
|
|
95
|
+
|
|
96
|
+
# Modify a scaffold file
|
|
97
|
+
claude = project / "CLAUDE.md"
|
|
98
|
+
original = claude.read_text()
|
|
99
|
+
claude.write_text("OLD CONTENT")
|
|
100
|
+
|
|
101
|
+
# Sync should overwrite it
|
|
102
|
+
result = main(["sync"])
|
|
103
|
+
assert result == 0
|
|
104
|
+
assert claude.read_text() == original
|
|
105
|
+
|
|
106
|
+
# Model files should be untouched
|
|
107
|
+
assert (project / "models" / "bracket" / "part.py").exists()
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_sync_not_a_workspace(tmp_path, monkeypatch):
|
|
111
|
+
monkeypatch.chdir(tmp_path)
|
|
112
|
+
result = main(["sync"])
|
|
113
|
+
assert result == 1
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_sync_dry_run_does_not_overwrite(tmp_path, monkeypatch):
|
|
117
|
+
monkeypatch.chdir(tmp_path)
|
|
118
|
+
main(["new", "bracket"])
|
|
119
|
+
project = tmp_path / "bracket"
|
|
120
|
+
monkeypatch.chdir(project)
|
|
121
|
+
claude = project / "CLAUDE.md"
|
|
122
|
+
claude.write_text("LOCAL", encoding="utf-8")
|
|
123
|
+
|
|
124
|
+
result = main(["sync", "--dry-run"])
|
|
125
|
+
assert result == 0
|
|
126
|
+
assert claude.read_text(encoding="utf-8") == "LOCAL"
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_probe_cx_cy_alias(monkeypatch, tmp_path):
|
|
130
|
+
monkeypatch.chdir(tmp_path)
|
|
131
|
+
main(["new", "bracket"])
|
|
132
|
+
monkeypatch.chdir(tmp_path / "bracket")
|
|
133
|
+
captured = {}
|
|
134
|
+
|
|
135
|
+
def fake_probe(project_path, model_name, z_values=None, x_values=None, y_values=None, center=None, region=None):
|
|
136
|
+
captured["center"] = center
|
|
137
|
+
return {"ok": True, "stage": "probe", "model": model_name}
|
|
138
|
+
|
|
139
|
+
monkeypatch.setattr(cli_mod, "probe_model", fake_probe)
|
|
140
|
+
result = main([
|
|
141
|
+
"probe", "bracket",
|
|
142
|
+
"--z", "1.0", "--cx", "-10.5", "--cy", "4.25",
|
|
143
|
+
])
|
|
144
|
+
assert result == 0
|
|
145
|
+
assert captured["center"] == (-10.5, 4.25)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def test_probe_center_and_cx_merge(monkeypatch, tmp_path):
|
|
149
|
+
monkeypatch.chdir(tmp_path)
|
|
150
|
+
main(["new", "bracket"])
|
|
151
|
+
monkeypatch.chdir(tmp_path / "bracket")
|
|
152
|
+
captured = {}
|
|
153
|
+
|
|
154
|
+
def fake_probe(project_path, model_name, z_values=None, x_values=None, y_values=None, center=None, region=None):
|
|
155
|
+
captured["center"] = center
|
|
156
|
+
return {"ok": True, "stage": "probe", "model": model_name}
|
|
157
|
+
|
|
158
|
+
monkeypatch.setattr(cli_mod, "probe_model", fake_probe)
|
|
159
|
+
result = main([
|
|
160
|
+
"probe", "bracket",
|
|
161
|
+
"--z", "1.0", "--center=1,2", "--cx", "3",
|
|
162
|
+
])
|
|
163
|
+
assert result == 0
|
|
164
|
+
assert captured["center"] == (3.0, 2.0)
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
"""Tests for CLI dispatch and auto-init behavior."""
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
|
|
4
|
-
import json
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
|
|
7
|
-
import agentcad.cli as cli_mod
|
|
8
|
-
from agentcad.cli import main
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def test_new_auto_init(tmp_path):
|
|
12
|
-
result = main(["new", "--project", str(tmp_path / "newproject"), "bracket"])
|
|
13
|
-
assert result == 0
|
|
14
|
-
assert (tmp_path / "newproject" / "cadproject.json").exists()
|
|
15
|
-
assert (tmp_path / "newproject" / "CLAUDE.md").exists()
|
|
16
|
-
assert (tmp_path / "newproject" / "models" / "bracket" / "part.py").exists()
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def test_init_creates_workspace_and_optional_model(tmp_path):
|
|
20
|
-
project = tmp_path / "initproj"
|
|
21
|
-
result = main(["init", "--project", str(project), "--model", "demo"])
|
|
22
|
-
assert result == 0
|
|
23
|
-
assert (project / "cadproject.json").exists()
|
|
24
|
-
assert (project / "models" / "demo" / "part.py").exists()
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def test_new_default_creates_project_dir_named_after_model(tmp_path, monkeypatch):
|
|
28
|
-
monkeypatch.chdir(tmp_path)
|
|
29
|
-
result = main(["new", "fan8025"])
|
|
30
|
-
assert result == 0
|
|
31
|
-
assert (tmp_path / "fan8025" / "cadproject.json").exists()
|
|
32
|
-
assert (tmp_path / "fan8025" / "models" / "fan8025" / "part.py").exists()
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def test_new_duplicate_fails(tmp_path):
|
|
36
|
-
project = tmp_path / "proj"
|
|
37
|
-
main(["new", "--project", str(project), "bracket"])
|
|
38
|
-
result = main(["new", "--project", str(project), "bracket"])
|
|
39
|
-
assert result == 1
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def test_new_duplicate_force(tmp_path):
|
|
43
|
-
project = tmp_path / "proj"
|
|
44
|
-
main(["new", "--project", str(project), "bracket"])
|
|
45
|
-
result = main(["new", "--project", str(project), "bracket", "--force"])
|
|
46
|
-
assert result == 0
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def test_build_missing_model(tmp_path):
|
|
50
|
-
project = tmp_path / "proj"
|
|
51
|
-
main(["new", "--project", str(project), "bracket"])
|
|
52
|
-
result = main(["build", "--project", str(project), "nonexistent"])
|
|
53
|
-
assert result == 1
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def test_validate_default_model(tmp_path):
|
|
57
|
-
"""Validate the default scaffold model (should build and validate ok)."""
|
|
58
|
-
project = tmp_path / "proj"
|
|
59
|
-
main(["new", "--project", str(project), "test_block"])
|
|
60
|
-
result = main(["validate", "--project", str(project), "test_block"])
|
|
61
|
-
assert result == 0
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def test_version():
|
|
65
|
-
import pytest
|
|
66
|
-
with pytest.raises(SystemExit) as exc_info:
|
|
67
|
-
main(["--version"])
|
|
68
|
-
assert exc_info.value.code == 0
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def test_sync_updates_workspace(tmp_path):
|
|
72
|
-
project = tmp_path / "proj"
|
|
73
|
-
main(["new", "--project", str(project), "bracket"])
|
|
74
|
-
|
|
75
|
-
# Modify a scaffold file
|
|
76
|
-
claude = project / "CLAUDE.md"
|
|
77
|
-
original = claude.read_text()
|
|
78
|
-
claude.write_text("OLD CONTENT")
|
|
79
|
-
|
|
80
|
-
# Sync should overwrite it
|
|
81
|
-
result = main(["sync", "--project", str(project)])
|
|
82
|
-
assert result == 0
|
|
83
|
-
assert claude.read_text() == original
|
|
84
|
-
|
|
85
|
-
# Model files should be untouched
|
|
86
|
-
assert (project / "models" / "bracket" / "part.py").exists()
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def test_sync_not_a_workspace(tmp_path):
|
|
90
|
-
result = main(["sync", "--project", str(tmp_path)])
|
|
91
|
-
assert result == 1
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def test_sync_dry_run_does_not_overwrite(tmp_path):
|
|
95
|
-
project = tmp_path / "proj"
|
|
96
|
-
main(["new", "--project", str(project), "bracket"])
|
|
97
|
-
claude = project / "CLAUDE.md"
|
|
98
|
-
claude.write_text("LOCAL", encoding="utf-8")
|
|
99
|
-
|
|
100
|
-
result = main(["sync", "--project", str(project), "--dry-run"])
|
|
101
|
-
assert result == 0
|
|
102
|
-
assert claude.read_text(encoding="utf-8") == "LOCAL"
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def test_probe_cx_cy_alias(monkeypatch, tmp_path):
|
|
106
|
-
project = tmp_path / "proj"
|
|
107
|
-
main(["new", "--project", str(project), "bracket"])
|
|
108
|
-
captured = {}
|
|
109
|
-
|
|
110
|
-
def fake_probe(project_path, model_name, z_values=None, x_values=None, y_values=None, center=None, region=None):
|
|
111
|
-
captured["center"] = center
|
|
112
|
-
return {"ok": True, "stage": "probe", "model": model_name}
|
|
113
|
-
|
|
114
|
-
monkeypatch.setattr(cli_mod, "probe_model", fake_probe)
|
|
115
|
-
result = main([
|
|
116
|
-
"probe", "--project", str(project), "bracket",
|
|
117
|
-
"--z", "1.0", "--cx", "-10.5", "--cy", "4.25",
|
|
118
|
-
])
|
|
119
|
-
assert result == 0
|
|
120
|
-
assert captured["center"] == (-10.5, 4.25)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def test_probe_center_and_cx_merge(monkeypatch, tmp_path):
|
|
124
|
-
project = tmp_path / "proj"
|
|
125
|
-
main(["new", "--project", str(project), "bracket"])
|
|
126
|
-
captured = {}
|
|
127
|
-
|
|
128
|
-
def fake_probe(project_path, model_name, z_values=None, x_values=None, y_values=None, center=None, region=None):
|
|
129
|
-
captured["center"] = center
|
|
130
|
-
return {"ok": True, "stage": "probe", "model": model_name}
|
|
131
|
-
|
|
132
|
-
monkeypatch.setattr(cli_mod, "probe_model", fake_probe)
|
|
133
|
-
result = main([
|
|
134
|
-
"probe", "--project", str(project), "bracket",
|
|
135
|
-
"--z", "1.0", "--center=1,2", "--cx", "3",
|
|
136
|
-
])
|
|
137
|
-
assert result == 0
|
|
138
|
-
assert captured["center"] == (3.0, 2.0)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentcad_cli-0.1.2 → agentcad_cli-0.1.3}/src/agentcad/_templates/workspace/references/notes.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|