@atlisp/mcp 1.8.16 → 1.8.17
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.
- package/dist/atlisp-mcp.js +7 -7
- package/dist/handlers/3d-handlers.js +128 -0
- package/dist/handlers/batch-handlers.js +260 -0
- package/dist/handlers/block-handlers.js +214 -0
- package/dist/handlers/cad-handlers.js +180 -0
- package/dist/handlers/constraint-handlers.js +130 -0
- package/dist/handlers/dim-hatch-handlers.js +340 -0
- package/dist/handlers/draw-handlers.js +175 -0
- package/dist/handlers/edit-handlers.js +179 -0
- package/dist/handlers/entity-handlers.js +196 -0
- package/dist/handlers/external-handlers.js +218 -0
- package/dist/handlers/file-handlers.js +172 -0
- package/dist/handlers/function-handlers.js +158 -0
- package/dist/handlers/layer-handlers.js +181 -0
- package/dist/handlers/package-handlers.js +89 -0
- package/dist/handlers/parametric-handlers.js +272 -0
- package/dist/handlers/pdf-annotation-handlers.js +117 -0
- package/dist/handlers/prompt-handlers.js +9 -0
- package/dist/handlers/purge-handlers.js +137 -0
- package/dist/handlers/query-print-handlers.js +662 -0
- package/dist/handlers/resource-cache.js +63 -0
- package/dist/handlers/resource-defs.js +79 -0
- package/dist/handlers/resource-handlers.js +131 -0
- package/dist/handlers/resource-readers.js +1045 -0
- package/dist/handlers/sheetset-handlers.js +430 -0
- package/dist/handlers/spatial-handlers.js +174 -0
- package/dist/handlers/style-handlers.js +162 -0
- package/dist/handlers/text-handlers.js +198 -0
- package/dist/handlers/ucs-layout-handlers.js +271 -0
- package/dist/handlers/viewport-handlers.js +150 -0
- package/dist/handlers/xdata-handlers.js +148 -0
- package/dist/handlers/xref-handlers.js +334 -0
- package/dist/lisp-security.js +7 -2
- package/package.json +2 -2
package/dist/atlisp-mcp.js
CHANGED
|
@@ -1123,13 +1123,13 @@ var init_constants = __esm({
|
|
|
1123
1123
|
logging: {},
|
|
1124
1124
|
completions: {},
|
|
1125
1125
|
experimental: {
|
|
1126
|
-
pipeline_engine:
|
|
1127
|
-
triggers:
|
|
1128
|
-
repl:
|
|
1129
|
-
webhooks:
|
|
1130
|
-
agent_context:
|
|
1131
|
-
rate_limiting:
|
|
1132
|
-
request_dedup:
|
|
1126
|
+
pipeline_engine: true,
|
|
1127
|
+
triggers: true,
|
|
1128
|
+
repl: true,
|
|
1129
|
+
webhooks: true,
|
|
1130
|
+
agent_context: true,
|
|
1131
|
+
rate_limiting: true,
|
|
1132
|
+
request_dedup: true
|
|
1133
1133
|
}
|
|
1134
1134
|
};
|
|
1135
1135
|
MOCK_PACKAGES = [];
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { cad } from '../cad.js';
|
|
2
|
+
import { log } from '../logger.js';
|
|
3
|
+
import { mcpSuccess, mcpError, ensureCadConnected, escapeLispString } from '../handler-utils.js';
|
|
4
|
+
|
|
5
|
+
function parsePoint(point) {
|
|
6
|
+
if (Array.isArray(point)) return point.join(' ');
|
|
7
|
+
if (typeof point === 'string') return point;
|
|
8
|
+
return '0,0,0';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function createBox(center, length, width, height) {
|
|
12
|
+
try { await ensureCadConnected(); const pt = parsePoint(center); await cad.sendCommand(`(command "_.box" "${escapeLispString(pt)}" "${length}" "${width}" "${height}" "")`); return mcpSuccess(JSON.stringify({ center: pt, dimensions: { length, width, height } })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function createSphere(center, radius) {
|
|
16
|
+
try { await ensureCadConnected(); const pt = parsePoint(center); await cad.sendCommand(`(command "_.sphere" "${escapeLispString(pt)}" "${radius}" "")`); return mcpSuccess(JSON.stringify({ center: pt, radius })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function createCylinder(center, radius, height) {
|
|
20
|
+
try { await ensureCadConnected(); const pt = parsePoint(center); await cad.sendCommand(`(command "_.cylinder" "${escapeLispString(pt)}" "${radius}" "${height}" "")`); return mcpSuccess(JSON.stringify({ center: pt, radius, height })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function createCone(center, radius, height) {
|
|
24
|
+
try { await ensureCadConnected(); const pt = parsePoint(center); await cad.sendCommand(`(command "_.cone" "${escapeLispString(pt)}" "${radius}" "${height}" "")`); return mcpSuccess(JSON.stringify({ center: pt, radius, height })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function createTorus(center, majorRadius, minorRadius) {
|
|
28
|
+
try { await ensureCadConnected(); const pt = parsePoint(center); await cad.sendCommand(`(command "_.torus" "${escapeLispString(pt)}" "${majorRadius}" "${minorRadius}" "")`); return mcpSuccess(JSON.stringify({ center: pt, majorRadius, minorRadius })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function createWedge(center, length, width, height) {
|
|
32
|
+
try { await ensureCadConnected(); const pt = parsePoint(center); await cad.sendCommand(`(command "_.wedge" "${escapeLispString(pt)}" "${length}" "${width}" "${height}" "")`); return mcpSuccess(JSON.stringify({ center: pt, dimensions: { length, width, height } })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function create3DFace(points) {
|
|
36
|
+
try { await ensureCadConnected(); const ptList = Array.isArray(points) ? points.join(' ') : points; await cad.sendCommand(`(command "_.3dface" ${ptList} "")`); return mcpSuccess(JSON.stringify({ points })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function createMesh(rows, columns, points) {
|
|
40
|
+
try { await ensureCadConnected(); const ptList = typeof points === 'string' ? points : (Array.isArray(points) ? points.join(' ') : points); await cad.sendCommand(`(command "_.mesh" "${rows}" "${columns}" ${ptList} "")`); return mcpSuccess(JSON.stringify({ rows, columns })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function extrudeSolid(profileHandle, height, taperAngle = 0) {
|
|
44
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.extrude" (handent "${escapeLispString(profileHandle)}") "${height}" "${taperAngle}" "")`); return mcpSuccess(JSON.stringify({ profileHandle, height, taperAngle })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function revolveSolid(profileHandle, axisStart, axisEnd, angle = 360) {
|
|
48
|
+
try { await ensureCadConnected(); const startPt = parsePoint(axisStart); const endPt = parsePoint(axisEnd); await cad.sendCommand(`(command "_.revolve" (handent "${escapeLispString(profileHandle)}") "${escapeLispString(startPt)}" "${escapeLispString(endPt)}" "${angle}" "")`); return mcpSuccess(JSON.stringify({ profileHandle, axisStart: startPt, axisEnd: endPt, angle })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function create3DPolyline(points) {
|
|
52
|
+
try { await ensureCadConnected(); const ptList = Array.isArray(points) ? points.map(p => parsePoint(p)).join(' ') : points; await cad.sendCommand(`(command "_.3dpoly" ${ptList} "")`); return mcpSuccess(JSON.stringify({ points })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function createRegion(handles) {
|
|
56
|
+
try { await ensureCadConnected(); const handleList = Array.isArray(handles) ? handles : handles.split(',').map(h => h.trim()); const handleStr = handleList.map(h => `(handent "${escapeLispString(h)}")`).join(' '); await cad.sendCommand(`(command "_.region" ${handleStr} "")`); return mcpSuccess(JSON.stringify({ handleCount: handleList.length })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function booleanUnion(handles) {
|
|
60
|
+
try { await ensureCadConnected(); const handleList = Array.isArray(handles) ? handles : handles.split(',').map(h => h.trim()); await cad.sendCommand(`(command "_.union" ${handleList.map(h => `(handent "${escapeLispString(h)}")`).join(' ')} "")`); return mcpSuccess(JSON.stringify({ operation: 'union' })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function booleanSubtract(handles, subtractFromHandles = []) {
|
|
64
|
+
try {
|
|
65
|
+
await ensureCadConnected();
|
|
66
|
+
const handleList = Array.isArray(handles) ? handles : handles.split(',').map(h => h.trim());
|
|
67
|
+
const fromList = subtractFromHandles.length ? (Array.isArray(subtractFromHandles) ? subtractFromHandles : subtractFromHandles.split(',').map(h => h.trim())) : [handleList.shift()];
|
|
68
|
+
const fromStr = fromList.map(h => `(handent "${escapeLispString(h)}")`).join(' ');
|
|
69
|
+
const subtractStr = handleList.map(h => `(handent "${escapeLispString(h)}")`).join(' ');
|
|
70
|
+
await cad.sendCommand(`(command "_.subtract" ${fromStr} "" ${subtractStr} "")`);
|
|
71
|
+
return mcpSuccess(JSON.stringify({ subtractFrom: fromList, subtractThese: handleList }));
|
|
72
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function booleanIntersect(handles) {
|
|
76
|
+
try { await ensureCadConnected(); const handleList = Array.isArray(handles) ? handles : handles.split(',').map(h => h.trim()); await cad.sendCommand(`(command "_.intersect" ${handleList.map(h => `(handent "${escapeLispString(h)}")`).join(' ')} "")`); return mcpSuccess(JSON.stringify({ operation: 'intersect' })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function sliceSolid(solidHandle, planePoint, planeNormal, keepBoth = true) {
|
|
80
|
+
try { await ensureCadConnected(); const pt = parsePoint(planePoint); const normal = parsePoint(planeNormal); const side = keepBoth ? 'Both' : 'No'; await cad.sendCommand(`(command "_.slice" (handent "${escapeLispString(solidHandle)}") "${escapeLispString(pt)}" "${escapeLispString(normal)}" "${side}")`); return mcpSuccess(JSON.stringify({ solidHandle, planePoint: pt, planeNormal: normal, keepBoth })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function createLoftSurface(profileHandles, guideHandles = []) {
|
|
84
|
+
try {
|
|
85
|
+
await ensureCadConnected();
|
|
86
|
+
const profileList = Array.isArray(profileHandles) ? profileHandles : profileHandles.split(',').map(h => h.trim());
|
|
87
|
+
const guideList = Array.isArray(guideHandles) ? guideHandles : guideHandles.split(',').map(h => h.trim());
|
|
88
|
+
const cmd = `(progn
|
|
89
|
+
(command "_.loft")
|
|
90
|
+
${profileList.map(h => `(handent "${escapeLispString(h)}")`).join(' ')}
|
|
91
|
+
${guideList.length > 0 ? guideList.map(h => `(handent "${escapeLispString(h)}")`).join(' ') : ''}
|
|
92
|
+
""
|
|
93
|
+
)`;
|
|
94
|
+
await cad.sendCommand(cmd);
|
|
95
|
+
return mcpSuccess(JSON.stringify({ profileCount: profileList.length, guideCount: guideList.length }));
|
|
96
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export async function get3DSolidInfo(handle) {
|
|
100
|
+
try {
|
|
101
|
+
await ensureCadConnected();
|
|
102
|
+
const result = await cad.sendCommandWithResult(`(progn
|
|
103
|
+
(setq ent (handent "${escapeLispString(handle)}"))
|
|
104
|
+
(if ent
|
|
105
|
+
(progn
|
|
106
|
+
(setq vla (vlax-ename->vla-object ent))
|
|
107
|
+
(princ (vl-prin1-to-string (list
|
|
108
|
+
(cons "type" (vla-get-objectname vla))
|
|
109
|
+
(cons "volume" (vla-get-volume vla))
|
|
110
|
+
(cons "surfaceArea" (vla-get-area vla))
|
|
111
|
+
)))
|
|
112
|
+
)
|
|
113
|
+
(princ "nil")
|
|
114
|
+
)
|
|
115
|
+
)`);
|
|
116
|
+
let info = {};
|
|
117
|
+
if (result && result !== 'nil') { try { info = JSON.parse(result); } catch { info = {}; } }
|
|
118
|
+
return mcpSuccess(JSON.stringify({ handle, info }));
|
|
119
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function thickenSurface(surfaceHandle, thickness) {
|
|
123
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.thicken" (handent "${escapeLispString(surfaceHandle)}") "${thickness}")`); return mcpSuccess(JSON.stringify({ surfaceHandle, thickness })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export async function offsetSurface(surfaceHandle, distance) {
|
|
127
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.offset" (handent "${escapeLispString(surfaceHandle)}") "${distance}")`); return mcpSuccess(JSON.stringify({ surfaceHandle, distance })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
128
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { cad } from '../cad.js';
|
|
2
|
+
import { log } from '../logger.js';
|
|
3
|
+
import { mcpSuccess, mcpError, ensureCadConnected, escapeLispString } from '../handler-utils.js';
|
|
4
|
+
|
|
5
|
+
function parseHandleList(handles) {
|
|
6
|
+
if (typeof handles === 'string') {
|
|
7
|
+
const trimmed = handles.trim();
|
|
8
|
+
if (trimmed.startsWith('[')) {
|
|
9
|
+
try { handles = JSON.parse(trimmed); } catch { handles = handles.split(',').map(h => h.trim()); }
|
|
10
|
+
} else {
|
|
11
|
+
handles = handles.split(',').map(h => h.trim());
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if (!Array.isArray(handles)) handles = [handles];
|
|
15
|
+
return handles;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function batchRename(handles, newNameTemplate, startNum = 1) {
|
|
19
|
+
try {
|
|
20
|
+
await ensureCadConnected();
|
|
21
|
+
const handleList = parseHandleList(handles);
|
|
22
|
+
const results = [];
|
|
23
|
+
for (let i = 0; i < handleList.length; i++) {
|
|
24
|
+
const handle = handleList[i];
|
|
25
|
+
const newName = newNameTemplate.replace('{n}', String(startNum + i).padStart(3, '0'));
|
|
26
|
+
try {
|
|
27
|
+
await cad.sendCommand(`(_vlax-set-property (vla-item (vla-get-blocks (vla-get-document (vlax-ename->vla-object (handent "${escapeLispString(handle)}")))) (handent "${escapeLispString(handle)}")) 'Name "${escapeLispString(newName)}")`);
|
|
28
|
+
results.push({ handle, newName, success: true });
|
|
29
|
+
} catch (e) {
|
|
30
|
+
results.push({ handle, error: e.message, success: false });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return mcpSuccess(JSON.stringify(results));
|
|
34
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function batchMove(handles, fromLayer, toLayer) {
|
|
38
|
+
try {
|
|
39
|
+
await ensureCadConnected();
|
|
40
|
+
const handleList = parseHandleList(handles);
|
|
41
|
+
const results = [];
|
|
42
|
+
for (const handle of handleList) {
|
|
43
|
+
try {
|
|
44
|
+
const cond = fromLayer ? `(= (cdr (assoc 8 (entget ent))) "${escapeLispString(fromLayer)}")` : 't';
|
|
45
|
+
await cad.sendCommand(`(progn (setq ent (handent "${escapeLispString(handle)}")) (if ${cond} (entmod (subst (cons 8 "${escapeLispString(toLayer)}") (assoc 8 (entget ent)) (entget ent)))))`);
|
|
46
|
+
results.push({ handle, fromLayer, toLayer, success: true });
|
|
47
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
48
|
+
}
|
|
49
|
+
return mcpSuccess(JSON.stringify(results));
|
|
50
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function batchCopy(handles, dx, dy, dz = 0) {
|
|
54
|
+
try {
|
|
55
|
+
await ensureCadConnected();
|
|
56
|
+
const handleList = parseHandleList(handles);
|
|
57
|
+
const results = [];
|
|
58
|
+
for (const handle of handleList) {
|
|
59
|
+
try {
|
|
60
|
+
await cad.sendCommand(`(command "_.copy" (handent "${escapeLispString(handle)}") "" (list 0 0 0) (list ${dx} ${dy} ${dz}))`);
|
|
61
|
+
results.push({ originalHandle: handle, offset: { dx, dy, dz }, success: true });
|
|
62
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
63
|
+
}
|
|
64
|
+
return mcpSuccess(JSON.stringify(results));
|
|
65
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function batchDelete(handles) {
|
|
69
|
+
try {
|
|
70
|
+
await ensureCadConnected();
|
|
71
|
+
const handleList = parseHandleList(handles);
|
|
72
|
+
const results = [];
|
|
73
|
+
for (const handle of handleList) {
|
|
74
|
+
try {
|
|
75
|
+
await cad.sendCommand(`(entdel (handent "${escapeLispString(handle)}"))`);
|
|
76
|
+
results.push({ handle, success: true });
|
|
77
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
78
|
+
}
|
|
79
|
+
return mcpSuccess(JSON.stringify(results));
|
|
80
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function batchSetColor(handles, color) {
|
|
84
|
+
try {
|
|
85
|
+
await ensureCadConnected();
|
|
86
|
+
const handleList = parseHandleList(handles);
|
|
87
|
+
const results = [];
|
|
88
|
+
for (const handle of handleList) {
|
|
89
|
+
try {
|
|
90
|
+
await cad.sendCommand(`(progn (setq ent (handent "${escapeLispString(handle)}")) (entmod (subst (cons 62 ${color}) (assoc 62 (entget ent)) (entget ent))) (princ "ok"))`);
|
|
91
|
+
results.push({ handle, color, success: true });
|
|
92
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
93
|
+
}
|
|
94
|
+
return mcpSuccess(JSON.stringify(results));
|
|
95
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function batchExplode(handles) {
|
|
99
|
+
try {
|
|
100
|
+
await ensureCadConnected();
|
|
101
|
+
const handleList = parseHandleList(handles);
|
|
102
|
+
const results = [];
|
|
103
|
+
for (const handle of handleList) {
|
|
104
|
+
try {
|
|
105
|
+
await cad.sendCommand(`(progn (command "_.explode" (handent "${escapeLispString(handle)}")) (princ "ok"))`);
|
|
106
|
+
results.push({ handle, success: true });
|
|
107
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
108
|
+
}
|
|
109
|
+
return mcpSuccess(JSON.stringify(results));
|
|
110
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export async function batchMirror(handles, startPoint, endPoint, deleteOriginal = false) {
|
|
114
|
+
try {
|
|
115
|
+
await ensureCadConnected();
|
|
116
|
+
const handleList = parseHandleList(handles);
|
|
117
|
+
const results = [];
|
|
118
|
+
for (const handle of handleList) {
|
|
119
|
+
try {
|
|
120
|
+
const pt1 = typeof startPoint === 'string' ? startPoint : startPoint.join(' ');
|
|
121
|
+
const pt2 = typeof endPoint === 'string' ? endPoint : endPoint.join(' ');
|
|
122
|
+
const delOpt = deleteOriginal ? 'yes' : 'no';
|
|
123
|
+
await cad.sendCommand(`(progn (command "_.mirror" (handent "${escapeLispString(handle)}") "" "${escapeLispString(pt1)}" "${escapeLispString(pt2)}" "${delOpt}") (princ "ok"))`);
|
|
124
|
+
results.push({ handle, success: true });
|
|
125
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
126
|
+
}
|
|
127
|
+
return mcpSuccess(JSON.stringify(results));
|
|
128
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export async function batchOffset(handles, distance, side = 'both') {
|
|
132
|
+
try {
|
|
133
|
+
await ensureCadConnected();
|
|
134
|
+
const handleList = parseHandleList(handles);
|
|
135
|
+
const results = [];
|
|
136
|
+
for (const handle of handleList) {
|
|
137
|
+
try {
|
|
138
|
+
if (side === 'both') {
|
|
139
|
+
await cad.sendCommand(`(command "_.offset" ${distance} (handent "${escapeLispString(handle)}") (list 0 0 0))`);
|
|
140
|
+
} else {
|
|
141
|
+
await cad.sendCommand(`(command "_.offset" ${distance} (handent "${escapeLispString(handle)}"))`);
|
|
142
|
+
}
|
|
143
|
+
results.push({ handle, distance, success: true });
|
|
144
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
145
|
+
}
|
|
146
|
+
return mcpSuccess(JSON.stringify(results));
|
|
147
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export async function batchRotate(handles, angle, basePoint = null) {
|
|
151
|
+
try {
|
|
152
|
+
await ensureCadConnected();
|
|
153
|
+
const handleList = parseHandleList(handles);
|
|
154
|
+
const base = basePoint ? (Array.isArray(basePoint) ? basePoint.join(' ') : basePoint) : '0,0';
|
|
155
|
+
const results = [];
|
|
156
|
+
for (const handle of handleList) {
|
|
157
|
+
try {
|
|
158
|
+
await cad.sendCommand(`(command "_.rotate" (handent "${escapeLispString(handle)}") "" "${escapeLispString(base)}" "${angle}")`);
|
|
159
|
+
results.push({ handle, angle, success: true });
|
|
160
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
161
|
+
}
|
|
162
|
+
return mcpSuccess(JSON.stringify(results));
|
|
163
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export async function batchScale(handles, scaleFactor, basePoint = null) {
|
|
167
|
+
try {
|
|
168
|
+
await ensureCadConnected();
|
|
169
|
+
const handleList = parseHandleList(handles);
|
|
170
|
+
const base = basePoint ? (Array.isArray(basePoint) ? basePoint.join(' ') : basePoint) : '0,0';
|
|
171
|
+
const results = [];
|
|
172
|
+
for (const handle of handleList) {
|
|
173
|
+
try {
|
|
174
|
+
await cad.sendCommand(`(command "_.scale" (handent "${escapeLispString(handle)}") "" "${escapeLispString(base)}" "${scaleFactor}")`);
|
|
175
|
+
results.push({ handle, scaleFactor, success: true });
|
|
176
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
177
|
+
}
|
|
178
|
+
return mcpSuccess(JSON.stringify(results));
|
|
179
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export async function batchSetLinetype(handles, linetypeName) {
|
|
183
|
+
try {
|
|
184
|
+
await ensureCadConnected();
|
|
185
|
+
const handleList = parseHandleList(handles);
|
|
186
|
+
const results = [];
|
|
187
|
+
for (const handle of handleList) {
|
|
188
|
+
try {
|
|
189
|
+
await cad.sendCommand(`(progn (command "_.chltype" (handent "${escapeLispString(handle)}") "${escapeLispString(linetypeName)}") (princ "ok"))`);
|
|
190
|
+
results.push({ handle, linetype: linetypeName, success: true });
|
|
191
|
+
} catch (e) { results.push({ handle, error: e.message, success: false }); }
|
|
192
|
+
}
|
|
193
|
+
return mcpSuccess(JSON.stringify(results));
|
|
194
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export async function batchMatchProperties(sourceHandle, targetHandles) {
|
|
198
|
+
try {
|
|
199
|
+
await ensureCadConnected();
|
|
200
|
+
const handleList = parseHandleList(targetHandles);
|
|
201
|
+
const results = [];
|
|
202
|
+
for (const handle of handleList) {
|
|
203
|
+
try {
|
|
204
|
+
await cad.sendCommand(`(command "_.matchprop" (handent "${escapeLispString(sourceHandle)}") (handent "${escapeLispString(handle)}"))`);
|
|
205
|
+
results.push({ from: sourceHandle, to: handle, success: true });
|
|
206
|
+
} catch (e) { results.push({ from: sourceHandle, to: handle, error: e.message, success: false }); }
|
|
207
|
+
}
|
|
208
|
+
return mcpSuccess(JSON.stringify(results));
|
|
209
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export async function batchCreateGroup(name, handles) {
|
|
213
|
+
try {
|
|
214
|
+
await ensureCadConnected();
|
|
215
|
+
const handleList = parseHandleList(handles);
|
|
216
|
+
const handleStr = handleList.map(h => `(handent "${escapeLispString(h)}")`).join(' ');
|
|
217
|
+
const result = await cad.sendCommandWithResult(`(group (list ${handleStr}))`);
|
|
218
|
+
return mcpSuccess(JSON.stringify({ name, handle: result?.trim() }));
|
|
219
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export async function batchAddToGroup(groupName, handles) {
|
|
223
|
+
try {
|
|
224
|
+
await ensureCadConnected();
|
|
225
|
+
const handleList = parseHandleList(handles);
|
|
226
|
+
const results = [];
|
|
227
|
+
for (const handle of handleList) {
|
|
228
|
+
try {
|
|
229
|
+
await cad.sendCommand(`(progn (setq grp (cdr (assoc -3 (entget (tblobjname "group" "${escapeLispString(groupName)}"))))) (entmod (append (entget (tblobjname "group" "${escapeLispString(groupName)}")) (list (cons -3 (append grp (list (handent "${escapeLispString(handle)}"))))))) )`);
|
|
230
|
+
results.push({ handle, group: groupName, success: true });
|
|
231
|
+
} catch (e) { results.push({ handle, group: groupName, error: e.message, success: false }); }
|
|
232
|
+
}
|
|
233
|
+
return mcpSuccess(JSON.stringify(results));
|
|
234
|
+
} catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export async function moveEntity(handle, dx, dy, dz = 0) {
|
|
238
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.MOVE" (handent "${escapeLispString(handle)}") "" (list ${dx} ${dy} ${dz}) "")\n`); return mcpSuccess(JSON.stringify({ handle, dx, dy, dz })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
239
|
+
}
|
|
240
|
+
export async function copyEntity(handle, dx, dy, dz = 0) {
|
|
241
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.COPY" (handent "${escapeLispString(handle)}") "" (list ${dx} ${dy} ${dz}) "")\n`); return mcpSuccess(JSON.stringify({ handle, dx, dy, dz })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
242
|
+
}
|
|
243
|
+
export async function rotateEntity(handle, angle, basePoint = '0,0') {
|
|
244
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.ROTATE" (handent "${escapeLispString(handle)}") "" (list ${(basePoint||'0,0').replace(/,/g,' ')}) ${angle})\n`); return mcpSuccess(JSON.stringify({ handle, angle, basePoint })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
245
|
+
}
|
|
246
|
+
export async function scaleEntity(handle, scaleFactor, basePoint = '0,0') {
|
|
247
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.SCALE" (handent "${escapeLispString(handle)}") "" (list ${(basePoint||'0,0').replace(/,/g,' ')}) ${scaleFactor})\n`); return mcpSuccess(JSON.stringify({ handle, scaleFactor, basePoint })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
248
|
+
}
|
|
249
|
+
export async function mirrorEntity(handle, startPoint, endPoint, deleteOriginal = false) {
|
|
250
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.MIRROR" (handent "${escapeLispString(handle)}") "" (list ${startPoint.replace(/,/g,' ')}) (list ${endPoint.replace(/,/g,' ')}) ${deleteOriginal ? '"_Y"' : '"_N"'})\n`); return mcpSuccess(JSON.stringify({ handle, startPoint, endPoint, deleteOriginal })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
251
|
+
}
|
|
252
|
+
export async function offsetEntity(handle, distance, side) {
|
|
253
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.OFFSET" ${distance} (handent "${escapeLispString(handle)}") (list ${side.replace(/,/g,' ')}) "")\n`); return mcpSuccess(JSON.stringify({ handle, distance, side })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
254
|
+
}
|
|
255
|
+
export async function arrayRectangular(handle, rows, cols, rowSpacing, colSpacing) {
|
|
256
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.ARRAY" (handent "${escapeLispString(handle)}") "" "_R" ${rows} ${cols} ${rowSpacing} ${colSpacing})\n`); return mcpSuccess(JSON.stringify({ handle, rows, cols, rowSpacing, colSpacing })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
257
|
+
}
|
|
258
|
+
export async function arrayPolar(handle, center, count, angle = 360) {
|
|
259
|
+
try { await ensureCadConnected(); await cad.sendCommand(`(command "_.ARRAY" (handent "${escapeLispString(handle)}") "" "_P" (list ${center.replace(/,/g,' ')}) ${count} ${angle} "")\n`); return mcpSuccess(JSON.stringify({ handle, center, count, angle })); } catch (e) { return mcpError(`错误: ${e.message}`); }
|
|
260
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { cad } from '../cad.js';
|
|
2
|
+
import { mcpSuccess, mcpError, escapeLispString, getNotifyProgress } from '../handler-utils.js';
|
|
3
|
+
|
|
4
|
+
export async function createBlock(name, entities) {
|
|
5
|
+
if (!cad.connected) { await cad.connect(); }
|
|
6
|
+
if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
|
|
7
|
+
|
|
8
|
+
const code = `(progn
|
|
9
|
+
(vl-load-com)
|
|
10
|
+
(if (not (tblsearch "BLOCK" "${escapeLispString(name)}"))
|
|
11
|
+
(progn
|
|
12
|
+
(entmake
|
|
13
|
+
(list
|
|
14
|
+
(cons 0 "BLOCK")
|
|
15
|
+
(cons 70 0)
|
|
16
|
+
(cons 2 "${escapeLispString(name)}")
|
|
17
|
+
(cons 10 (list 0 0 0))
|
|
18
|
+
)
|
|
19
|
+
)
|
|
20
|
+
${entities}
|
|
21
|
+
(entmake (list (cons 0 "ENDBLK")))
|
|
22
|
+
"CREATED"
|
|
23
|
+
)
|
|
24
|
+
"EXISTS"
|
|
25
|
+
)
|
|
26
|
+
)`;
|
|
27
|
+
try {
|
|
28
|
+
const result = await cad.sendCommandWithResult(code);
|
|
29
|
+
if (result === 'CREATED' || result === '"CREATED"') {
|
|
30
|
+
return { content: [{ type: 'text', text: `已创建块: ${name}` }] };
|
|
31
|
+
}
|
|
32
|
+
if (result === 'EXISTS' || result === '"EXISTS"') {
|
|
33
|
+
return { content: [{ type: 'text', text: `块已存在: ${name}` }], isError: true };
|
|
34
|
+
}
|
|
35
|
+
return { content: [{ type: 'text', text: `创建失败: ${result}` }], isError: true };
|
|
36
|
+
} catch (e) {
|
|
37
|
+
return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function insertBlock(blockName, point, scale = 1, rotation = 0) {
|
|
42
|
+
if (!cad.connected) { await cad.connect(); }
|
|
43
|
+
if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
|
|
44
|
+
|
|
45
|
+
const coords = Array.isArray(point) ? point : point.split(',').map(s => parseFloat(s.trim()));
|
|
46
|
+
if (coords.length < 2) {
|
|
47
|
+
return { content: [{ type: 'text', text: '插入点格式错误,需要 x,y 或 [x,y,z]' }], isError: true };
|
|
48
|
+
}
|
|
49
|
+
const [x, y, z = 0] = coords;
|
|
50
|
+
|
|
51
|
+
const code = `(progn
|
|
52
|
+
(vl-load-com)
|
|
53
|
+
(if (tblsearch "BLOCK" "${escapeLispString(blockName)}")
|
|
54
|
+
(progn
|
|
55
|
+
(command "._INSERT" "${escapeLispString(blockName)}" (list ${x} ${y} ${z}) ${scale} ${rotation} 0 "")
|
|
56
|
+
"INSERTED"
|
|
57
|
+
)
|
|
58
|
+
"NOTFOUND"
|
|
59
|
+
)
|
|
60
|
+
)`;
|
|
61
|
+
try {
|
|
62
|
+
const result = await cad.sendCommandWithResult(code);
|
|
63
|
+
if (result === 'INSERTED' || result === '"INSERTED"') {
|
|
64
|
+
return { content: [{ type: 'text', text: `已插入块: ${blockName}` }] };
|
|
65
|
+
}
|
|
66
|
+
return { content: [{ type: 'text', text: `插入失败: ${result}` }], isError: true };
|
|
67
|
+
} catch (e) {
|
|
68
|
+
return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function getBlocks() {
|
|
73
|
+
if (!cad.connected) { await cad.connect(); }
|
|
74
|
+
if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
|
|
75
|
+
|
|
76
|
+
const code = `(progn
|
|
77
|
+
(vl-load-com)
|
|
78
|
+
(setq blocks nil)
|
|
79
|
+
(while (setq blk (tblnext "BLOCK" (null blocks)))
|
|
80
|
+
(setq blocks (cons (cdr (assoc 2 blk)) blocks))
|
|
81
|
+
)
|
|
82
|
+
(reverse blocks)
|
|
83
|
+
)`;
|
|
84
|
+
try {
|
|
85
|
+
const result = await cad.sendCommandWithResult(code);
|
|
86
|
+
if (!result || result === 'nil') {
|
|
87
|
+
return { content: [{ type: 'text', text: '当前图形中没有块定义' }] };
|
|
88
|
+
}
|
|
89
|
+
return { content: [{ type: 'text', text: result }] };
|
|
90
|
+
} catch (e) {
|
|
91
|
+
return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function batchGetBlockAttributes(args) {
|
|
96
|
+
if (!cad.connected) { await cad.connect(); }
|
|
97
|
+
if (!cad.connected) return mcpError('未连接 CAD');
|
|
98
|
+
try {
|
|
99
|
+
const filter = args.filter || '';
|
|
100
|
+
const blockName = args.blockName || '';
|
|
101
|
+
const lay = args.layer || '';
|
|
102
|
+
let lispFilter = '(ssget "_X" ';
|
|
103
|
+
const flist = [];
|
|
104
|
+
if (blockName) flist.push(`(cons 2 "${escapeLispString(blockName)}")`);
|
|
105
|
+
if (lay) flist.push(`(cons 8 "${escapeLispString(lay)}")`);
|
|
106
|
+
flist.push('(cons 0 "INSERT")');
|
|
107
|
+
lispFilter += `(list ${flist.join(' ')})`;
|
|
108
|
+
|
|
109
|
+
const code = `(progn
|
|
110
|
+
(vl-load-com)
|
|
111
|
+
(setq ss ${lispFilter})
|
|
112
|
+
(setq result nil)
|
|
113
|
+
(if ss
|
|
114
|
+
(progn
|
|
115
|
+
(vlax-for blk (vla-get-activeselectionset
|
|
116
|
+
(vla-get-activedocument (vlax-get-acad-object)))
|
|
117
|
+
(setq atts nil
|
|
118
|
+
atts-raw (vlax-invoke blk 'GetAttributes))
|
|
119
|
+
(if atts-raw
|
|
120
|
+
(foreach a atts-raw
|
|
121
|
+
(setq atts (cons (list (cons "tag" (vla-get-tagstring a))
|
|
122
|
+
(cons "value" (vla-get-textstring a))
|
|
123
|
+
(cons "handle" (vla-get-handle a))) atts)))
|
|
124
|
+
)
|
|
125
|
+
(setq result (cons (list (cons "handle" (vla-get-handle blk))
|
|
126
|
+
(cons "blockName" (vla-get-name blk))
|
|
127
|
+
(cons "layer" (vla-get-layer blk))
|
|
128
|
+
(cons "attributes" atts)) result))
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
(if result (vl-princ-to-string result) "[]")
|
|
133
|
+
)`;
|
|
134
|
+
const result = await cad.sendCommandWithResult(code);
|
|
135
|
+
return mcpSuccess(result || '[]');
|
|
136
|
+
} catch (e) {
|
|
137
|
+
return mcpError(`批量获取块属性失败: ${e.message}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export async function batchSetBlockAttributes(args) {
|
|
142
|
+
if (!cad.connected) { await cad.connect(); }
|
|
143
|
+
if (!cad.connected) return mcpError('未连接 CAD');
|
|
144
|
+
try {
|
|
145
|
+
const items = args.items || [];
|
|
146
|
+
let totalOk = 0;
|
|
147
|
+
let totalFail = 0;
|
|
148
|
+
const total = items.length;
|
|
149
|
+
for (let idx = 0; idx < total; idx++) {
|
|
150
|
+
const item = items[idx];
|
|
151
|
+
const np = getNotifyProgress();
|
|
152
|
+
if (np) np(idx + 1, total, `正在处理块 ${idx + 1}/${total}`);
|
|
153
|
+
try {
|
|
154
|
+
const handle = item.handle;
|
|
155
|
+
const attrs = item.attributes || {};
|
|
156
|
+
for (const [tag, value] of Object.entries(attrs)) {
|
|
157
|
+
await cad.sendCommandWithResult(
|
|
158
|
+
`(progn
|
|
159
|
+
(vl-load-com)
|
|
160
|
+
(if (setq ent (handent "${escapeLispString(handle)}"))
|
|
161
|
+
(progn
|
|
162
|
+
(setq vobj (vlax-ename->vla-object ent))
|
|
163
|
+
(setq atts (vlax-invoke vobj 'GetAttributes))
|
|
164
|
+
(if atts
|
|
165
|
+
(foreach a atts
|
|
166
|
+
(if (= (vla-get-tagstring a) "${escapeLispString(tag)}")
|
|
167
|
+
(vla-put-textstring a "${escapeLispString(String(value))}")
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
(princ "ok")
|
|
172
|
+
)
|
|
173
|
+
(princ "nf")
|
|
174
|
+
)
|
|
175
|
+
)`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
totalOk++;
|
|
179
|
+
} catch (e) {
|
|
180
|
+
totalFail++;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const msg = `批量设置块属性完成: 成功 ${totalOk}, 失败 ${totalFail}`;
|
|
184
|
+
if (totalFail > 0) return mcpError(msg);
|
|
185
|
+
return mcpSuccess(msg);
|
|
186
|
+
} catch (e) {
|
|
187
|
+
return mcpError(`批量设置块属性失败: ${e.message}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export async function explodeBlock(handle) {
|
|
192
|
+
if (!cad.connected) { await cad.connect(); }
|
|
193
|
+
if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
|
|
194
|
+
|
|
195
|
+
const code = `(progn
|
|
196
|
+
(vl-load-com)
|
|
197
|
+
(if (setq ent (handent "${escapeLispString(handle)}"))
|
|
198
|
+
(progn
|
|
199
|
+
(command "._EXPLODE" (ssadd ent (ssadd)))
|
|
200
|
+
"EXPLODED"
|
|
201
|
+
)
|
|
202
|
+
"NOTFOUND"
|
|
203
|
+
)
|
|
204
|
+
)`;
|
|
205
|
+
try {
|
|
206
|
+
const result = await cad.sendCommandWithResult(code);
|
|
207
|
+
if (result === 'EXPLODED' || result === '"EXPLODED"') {
|
|
208
|
+
return { content: [{ type: 'text', text: `已炸开块: ${handle}` }] };
|
|
209
|
+
}
|
|
210
|
+
return { content: [{ type: 'text', text: `操作失败: ${result}` }], isError: true };
|
|
211
|
+
} catch (e) {
|
|
212
|
+
return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
|
|
213
|
+
}
|
|
214
|
+
}
|