feat(templates): drawing_template_save on both engines — dwt_write is a declared capability

Live AutoCAD writes a real .dwt through SaveAs(path, ac2018_Template = 66) and
puts the description into the summary Comments; headlessly a .dxf template is
written through drawing_save_as and a .dwt request is refused with capability
dwt_write, naming the DXF route and the COM route. drawing_save_as's "dwt"
entry was 5 (acR13_dxf): a DWT request wrote an R13 DXF under a .dwt name.

Probed live on AutoCAD 2026 (typelib: ac2018_Template = 66, acR13_dxf = 5,
acTemplateDwg absent; the saved file starts AC1032, the document is rebound,
Comments takes). SECTION 19 is now 6 tools; SAVEAS joins SHARED_ACAD_COMMANDS;
templates/README.md documents the two files per template.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
Umut CAN
2026-09-21 22:48:31 +03:00
co-authored by Claude Opus 5
parent 17f7228fd6
commit b458923e19
9 changed files with 322 additions and 20 deletions
+39 -1
View File
@@ -6855,7 +6855,7 @@ async def pid_tag_parse(
# ---------------------------------------------------------------------------
# ── SECTION 19: Page Setup & Templates (5 tools) ────────────────────────────
# ── SECTION 19: Page Setup & Templates (6 tools) ────────────────────────────
# ---------------------------------------------------------------------------
@@ -7044,6 +7044,44 @@ async def drawing_template_list(ctx: Context = None) -> dict:
}
@cad_tool(
summary="Save the current drawing as a template: .dwt on live AutoCAD, .dxf headlessly.",
cost="mutate",
)
@mcp.tool(
annotations={"title": "Save As Template", "destructiveHint": False},
tags={"template", "drawing"},
)
async def drawing_template_save(
path: Annotated[str, "Destination .dwt (live AutoCAD) or .dxf (either engine)."],
name: Annotated[str | None, "Template name for the report (default: the file stem)."] = None,
description: Annotated[
str | None, "Template description → DWT summary Comments on the live engine."
] = None,
ctx: Context = None,
) -> dict:
"""AutoCAD's SAVEAS → Drawing Template, on both engines.
Live AutoCAD writes a real `.dwt` (`SaveAs(path, ac2018_Template)`) and
puts `description` into the template's summary Comments; the active
document is rebound to the new file, as SAVEAS does. Headlessly a `.dxf`
template is written — `drawing_new(template=<path>)` opens it — and a
`.dwt` request is refused with capability `dwt_write` (the message names
the DXF route and the COM route); a description is reported
`description_written: false` because DXF has nowhere to keep it. Any other
suffix, and any path outside the allowed directories, is refused before
a byte is written.
Pack: core · lean: no (`drawing_save_as` is not lean either).
"""
validated = validate_path(path, allow_write=True)
await ctx.info(f"Saving template: {validated}")
try:
return await _backend(ctx).drawing_template_save(str(validated), name, description)
except ValueError as exc:
raise ToolError(str(exc)) from exc
# ---------------------------------------------------------------------------
# ── RESOURCES ───────────────────────────────────────────────────────────────
# ---------------------------------------------------------------------------