@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.
Files changed (34) hide show
  1. package/dist/atlisp-mcp.js +7 -7
  2. package/dist/handlers/3d-handlers.js +128 -0
  3. package/dist/handlers/batch-handlers.js +260 -0
  4. package/dist/handlers/block-handlers.js +214 -0
  5. package/dist/handlers/cad-handlers.js +180 -0
  6. package/dist/handlers/constraint-handlers.js +130 -0
  7. package/dist/handlers/dim-hatch-handlers.js +340 -0
  8. package/dist/handlers/draw-handlers.js +175 -0
  9. package/dist/handlers/edit-handlers.js +179 -0
  10. package/dist/handlers/entity-handlers.js +196 -0
  11. package/dist/handlers/external-handlers.js +218 -0
  12. package/dist/handlers/file-handlers.js +172 -0
  13. package/dist/handlers/function-handlers.js +158 -0
  14. package/dist/handlers/layer-handlers.js +181 -0
  15. package/dist/handlers/package-handlers.js +89 -0
  16. package/dist/handlers/parametric-handlers.js +272 -0
  17. package/dist/handlers/pdf-annotation-handlers.js +117 -0
  18. package/dist/handlers/prompt-handlers.js +9 -0
  19. package/dist/handlers/purge-handlers.js +137 -0
  20. package/dist/handlers/query-print-handlers.js +662 -0
  21. package/dist/handlers/resource-cache.js +63 -0
  22. package/dist/handlers/resource-defs.js +79 -0
  23. package/dist/handlers/resource-handlers.js +131 -0
  24. package/dist/handlers/resource-readers.js +1045 -0
  25. package/dist/handlers/sheetset-handlers.js +430 -0
  26. package/dist/handlers/spatial-handlers.js +174 -0
  27. package/dist/handlers/style-handlers.js +162 -0
  28. package/dist/handlers/text-handlers.js +198 -0
  29. package/dist/handlers/ucs-layout-handlers.js +271 -0
  30. package/dist/handlers/viewport-handlers.js +150 -0
  31. package/dist/handlers/xdata-handlers.js +148 -0
  32. package/dist/handlers/xref-handlers.js +334 -0
  33. package/dist/lisp-security.js +7 -2
  34. package/package.json +2 -2
@@ -0,0 +1,162 @@
1
+ import { cad } from '../cad.js';
2
+ import { log } from '../logger.js';
3
+ import { mcpSuccess, mcpError, ensureCadConnected, escapeLispString } from '../handler-utils.js';
4
+
5
+ export async function createDimensionStyle(name, color = 'bylayer', arrow = 'ClosedFilled', textStyle = '') {
6
+ try {
7
+ await ensureCadConnected();
8
+ const result = await cad.sendCommandWithResult(`(progn
9
+ (command "_.dimstyle" "s" "${escapeLispString(name)}")
10
+ (command "_.dimstyle" "c" "${escapeLispString(color)}" "_.dimstyle" "a" "${escapeLispString(arrow)}")
11
+ (if (> (strlen "${escapeLispString(textStyle)}") 0) (command "_.dimstyle" "t" "${escapeLispString(textStyle)}"))
12
+ (princ "${escapeLispString(name)}")
13
+ )`);
14
+ return mcpSuccess(JSON.stringify({ name, color, arrow, textStyle, created: !!result }));
15
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
16
+ }
17
+
18
+ export async function setDimensionStyleVariable(styleName, variable, value) {
19
+ try {
20
+ await ensureCadConnected();
21
+ const result = await cad.sendCommandWithResult(`(progn
22
+ (command "_.dimstyle" "s" "${escapeLispString(styleName)}")
23
+ (command "_.dimstyle" "${escapeLispString(variable)}" "${escapeLispString(value)}")
24
+ (princ "ok")
25
+ )`);
26
+ return mcpSuccess(JSON.stringify({ styleName, variable, value, set: result?.includes('ok') }));
27
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
28
+ }
29
+
30
+ export async function listDimensionStyles() {
31
+ try {
32
+ await ensureCadConnected();
33
+ const result = await cad.sendCommandWithResult(`(progn
34
+ (setq styles nil)
35
+ (while (setq x (tblnext "dimstyle" (null styles)))
36
+ (setq styles (cons (cdr (assoc 2 x)) styles)))
37
+ (princ (vl-prin1-to-string (reverse styles)))
38
+ )`);
39
+ let styles = [];
40
+ if (result && result !== 'nil') { try { styles = JSON.parse(result); } catch { styles = result.replace(/[()]/g, '').split(' ').filter(Boolean); } }
41
+ return mcpSuccess(JSON.stringify({ styles, count: styles.length }));
42
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
43
+ }
44
+
45
+ export async function getDimensionStyleVariable(styleName, variable) {
46
+ try {
47
+ await ensureCadConnected();
48
+ const result = await cad.sendCommandWithResult(`(progn
49
+ (command "_.dimstyle" "s" "${escapeLispString(styleName)}")
50
+ (command "_.dimstyle" "${escapeLispString(variable)}")
51
+ (princ "done")
52
+ )`);
53
+ return mcpSuccess(JSON.stringify({ styleName, variable, value: result }));
54
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
55
+ }
56
+
57
+ export async function createTextStyle(name, fontFile, height = 0, width = 1, angle = 0) {
58
+ try {
59
+ await ensureCadConnected();
60
+ const result = await cad.sendCommandWithResult(`(progn
61
+ (command "_.style" "${escapeLispString(name)}" "${escapeLispString(fontFile)}" "${height}" "${width}" "${angle}" "n" "n")
62
+ (princ "${escapeLispString(name)}")
63
+ )`);
64
+ return mcpSuccess(JSON.stringify({ name, fontFile, height, width, angle, created: !!result }));
65
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
66
+ }
67
+
68
+ export async function listTextStyles() {
69
+ try {
70
+ await ensureCadConnected();
71
+ const result = await cad.sendCommandWithResult(`(progn
72
+ (setq styles nil)
73
+ (while (setq x (tblnext "style" (null styles)))
74
+ (setq styles (cons (cdr (assoc 2 x)) styles)))
75
+ (princ (vl-prin1-to-string (reverse styles)))
76
+ )`);
77
+ let styles = [];
78
+ if (result && result !== 'nil') { try { styles = JSON.parse(result); } catch { styles = []; } }
79
+ return mcpSuccess(JSON.stringify({ styles, count: styles.length }));
80
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
81
+ }
82
+
83
+ export async function createLinetype(name, description, pattern) {
84
+ try { await ensureCadConnected(); await cad.sendCommand(`(command "_.linetype" "c" "${escapeLispString(name)}" "${escapeLispString(description)}" "${escapeLispString(pattern)}" "")`); return mcpSuccess(JSON.stringify({ name, description })); } catch (e) { return mcpError(`错误: ${e.message}`); }
85
+ }
86
+
87
+ export async function loadLinetype(linetypeName, filePath) {
88
+ try { await ensureCadConnected(); await cad.sendCommand(`(command "_.linetype" "l" "${escapeLispString(linetypeName)}" "${escapeLispString(filePath)}")`); return mcpSuccess(JSON.stringify({ linetypeName, filePath })); } catch (e) { return mcpError(`错误: ${e.message}`); }
89
+ }
90
+
91
+ export async function listLinetypes() {
92
+ try {
93
+ await ensureCadConnected();
94
+ const result = await cad.sendCommandWithResult(`(progn
95
+ (setq lts nil)
96
+ (while (setq x (tblnext "ltype" (null lts)))
97
+ (setq lts (cons (cdr (assoc 2 x)) lts)))
98
+ (princ (vl-prin1-to-string (reverse lts)))
99
+ )`);
100
+ let linetypes = [];
101
+ if (result && result !== 'nil') { try { linetypes = JSON.parse(result); } catch { linetypes = []; } }
102
+ return mcpSuccess(JSON.stringify({ linetypes, count: linetypes.length }));
103
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
104
+ }
105
+
106
+ export async function createMLeaderStyle(name) {
107
+ try {
108
+ await ensureCadConnected();
109
+ const result = await cad.sendCommandWithResult(`(progn
110
+ (vl-load-com)
111
+ (setq mls (vla-get-mleaderstyles (vla-get-activedocument (vlax-get-acad-object))))
112
+ (vla-add mls "${escapeLispString(name)}")
113
+ (princ "${escapeLispString(name)}")
114
+ )`);
115
+ return mcpSuccess(JSON.stringify({ name, created: !!result }));
116
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
117
+ }
118
+
119
+ export async function setMLeaderStyleProperty(styleName, property, value) {
120
+ try {
121
+ await ensureCadConnected();
122
+ const valStr = typeof value === 'string' ? `"${escapeLispString(value)}"` : String(value);
123
+ const result = await cad.sendCommandWithResult(`(progn
124
+ (vl-load-com)
125
+ (setq mls (vla-get-mleaderstyles (vla-get-activedocument (vlax-get-acad-object))))
126
+ (vlax-for style mls (if (= (vla-get-name style) "${escapeLispString(styleName)}") (setf (vla-get-${escapeLispString(property)} style) ${valStr})))
127
+ (princ "ok")
128
+ )`);
129
+ return mcpSuccess(JSON.stringify({ styleName, property, value, set: result?.includes('ok') }));
130
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
131
+ }
132
+
133
+ export async function listMLeaderStyles() {
134
+ try {
135
+ await ensureCadConnected();
136
+ const result = await cad.sendCommandWithResult(`(progn
137
+ (vl-load-com)
138
+ (setq mls (vla-get-mleaderstyles (vla-get-activedocument (vlax-get-acad-object))) styles nil)
139
+ (vlax-for style mls (setq styles (cons (vla-get-name style) styles)))
140
+ (princ (vl-prin1-to-string (reverse styles)))
141
+ )`);
142
+ let styles = [];
143
+ if (result && result !== 'nil') { try { styles = JSON.parse(result); } catch { styles = []; } }
144
+ return mcpSuccess(JSON.stringify({ styles, count: styles.length }));
145
+ } catch (e) { return mcpError(`错误: ${e.message}`); }
146
+ }
147
+
148
+ export async function createCloudLine(startPoint, endPoint, bulge = 1, arcRadius = 0) {
149
+ try { await ensureCadConnected(); const start = Array.isArray(startPoint) ? startPoint.join(' ') : startPoint; const end = Array.isArray(endPoint) ? endPoint.join(' ') : endPoint; await cad.sendCommand(`(command "_.revcloud" "${escapeLispString(start)}" "${escapeLispString(end)}" "${bulge}" "")`); return mcpSuccess(JSON.stringify({ startPoint: start, endPoint: end, bulge })); } catch (e) { return mcpError(`错误: ${e.message}`); }
150
+ }
151
+
152
+ export async function convertToCloudLine(handle) {
153
+ try { await ensureCadConnected(); await cad.sendCommand(`(command "_.revcloud" (handent "${escapeLispString(handle)}") "")`); return mcpSuccess(JSON.stringify({ handle, converted: true })); } catch (e) { return mcpError(`错误: ${e.message}`); }
154
+ }
155
+
156
+ export async function setCloudLineStyle(bulgeFactor = 1, arcRadius = 0.5) {
157
+ try { await ensureCadConnected(); await cad.sendCommand(`(setvar "revcldbulge" ${bulgeFactor})`); return mcpSuccess(JSON.stringify({ bulgeFactor, arcRadius })); } catch (e) { return mcpError(`错误: ${e.message}`); }
158
+ }
159
+
160
+ export async function createMultileaderStyle(name) { return await createMLeaderStyle(name); }
161
+ export async function setMultileaderStyleProperty(styleName, property, value) { return await setMLeaderStyleProperty(styleName, property, value); }
162
+ export async function listMultileaderStyles() { return await listMLeaderStyles(); }
@@ -0,0 +1,198 @@
1
+ import { cad } from '../cad.js';
2
+ import { escapeLispString } from '../handler-utils.js';
3
+
4
+ export async function findText(params) {
5
+ if (!cad.connected) { await cad.connect(); }
6
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
7
+ try {
8
+ const caseSensitive = params.caseSensitive ? 'T' : 'nil';
9
+ const code = `(progn
10
+ (vl-load-com)
11
+ (setq ss (ssget "X" (list (cons 0 "TEXT,MTEXT") (cons 1 "${escapeLispString(params.pattern)}"))))
12
+ (if ss
13
+ (progn
14
+ (setq cnt (sslength ss) results nil i 0)
15
+ (while (< i cnt)
16
+ (setq ent (ssname ss i))
17
+ (setq h (cdr (assoc 5 (entget ent))))
18
+ (setq txt (cdr (assoc 1 (entget ent))))
19
+ (setq results (cons (list h txt) results))
20
+ (setq i (1+ i)))
21
+ (reverse results)
22
+ )
23
+ nil
24
+ )
25
+ )`;
26
+ const result = await cad.sendCommandWithResult(code);
27
+ if (!result || result === 'nil') {
28
+ return { content: [{ type: 'text', text: `未找到匹配 "${params.pattern}" 的文本` }] };
29
+ }
30
+ return { content: [{ type: 'text', text: result }] };
31
+ } catch (e) {
32
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
33
+ }
34
+ }
35
+
36
+ export async function replaceText(params) {
37
+ if (!cad.connected) { await cad.connect(); }
38
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
39
+ try {
40
+ const code = `(progn
41
+ (vl-load-com)
42
+ (setq cnt 0)
43
+ (if (setq ss (ssget "X" (list (cons 0 "TEXT,MTEXT") (cons 1 "${escapeLispString(params.pattern)}"))))
44
+ (progn
45
+ (setq i 0)
46
+ (while (< i (sslength ss))
47
+ (setq ent (ssname ss i))
48
+ (setq ed (entget ent))
49
+ (setq oldTxt (cdr (assoc 1 ed)))
50
+ (entmod (subst (cons 1 "${escapeLispString(params.replacement)}") (assoc 1 ed) ed))
51
+ (setq cnt (1+ cnt))
52
+ (setq i (1+ i)))
53
+ )
54
+ )
55
+ cnt
56
+ )`;
57
+ const result = await cad.sendCommandWithResult(code);
58
+ return { content: [{ type: 'text', text: `已替换 ${result || 0} 处文本` }] };
59
+ } catch (e) {
60
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
61
+ }
62
+ }
63
+
64
+ export async function setTextHeight(params) {
65
+ if (!cad.connected) { await cad.connect(); }
66
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
67
+ try {
68
+ const code = `(progn
69
+ (vl-load-com)
70
+ (if (setq ent (handent "${escapeLispString(params.handle)}"))
71
+ (progn
72
+ (setq ed (entget ent))
73
+ (entmod (subst (cons 40 ${params.height}) (assoc 40 ed) ed))
74
+ "OK"
75
+ )
76
+ "NOTFOUND"
77
+ )
78
+ )`;
79
+ const result = await cad.sendCommandWithResult(code);
80
+ if (result === 'OK' || result === '"OK"') {
81
+ return { content: [{ type: 'text', text: `已设置文字高度: ${params.height}` }] };
82
+ }
83
+ return { content: [{ type: 'text', text: `设置失败: ${result}` }], isError: true };
84
+ } catch (e) {
85
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
86
+ }
87
+ }
88
+
89
+ export async function setTextStyleName(params) {
90
+ if (!cad.connected) { await cad.connect(); }
91
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
92
+ try {
93
+ const code = `(progn
94
+ (vl-load-com)
95
+ (if (setq ent (handent "${escapeLispString(params.handle)}"))
96
+ (progn
97
+ (setq ed (entget ent))
98
+ (entmod (subst (cons 7 "${escapeLispString(params.styleName)}") (assoc 7 ed) ed))
99
+ "OK"
100
+ )
101
+ "NOTFOUND"
102
+ )
103
+ )`;
104
+ const result = await cad.sendCommandWithResult(code);
105
+ if (result === 'OK' || result === '"OK"') {
106
+ return { content: [{ type: 'text', text: `已设置文字样式: ${params.styleName}` }] };
107
+ }
108
+ return { content: [{ type: 'text', text: `设置失败: ${result}` }], isError: true };
109
+ } catch (e) {
110
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
111
+ }
112
+ }
113
+
114
+ export async function justifyText(params) {
115
+ if (!cad.connected) { await cad.connect(); }
116
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
117
+ try {
118
+ const justMap = {
119
+ 'TL': 1, 'TC': 2, 'TR': 3,
120
+ 'ML': 4, 'MC': 5, 'MR': 6,
121
+ 'BL': 7, 'BC': 8, 'BR': 9,
122
+ 'L': 0, 'C': 1, 'R': 2,
123
+ 'M': 4, 'B': 8, 'T': 2
124
+ };
125
+ const justVal = justMap[params.justification] || 0;
126
+ const code = `(progn
127
+ (vl-load-com)
128
+ (if (setq ent (handent "${escapeLispString(params.handle)}"))
129
+ (progn
130
+ (setq ed (entget ent))
131
+ (if (assoc 72 ed)
132
+ (entmod (subst (cons 72 ${justVal}) (assoc 72 ed) ed))
133
+ (entmod (append ed (list (cons 72 ${justVal}))))
134
+ )
135
+ "OK"
136
+ )
137
+ "NOTFOUND"
138
+ )
139
+ )`;
140
+ const result = await cad.sendCommandWithResult(code);
141
+ if (result === 'OK' || result === '"OK"') {
142
+ return { content: [{ type: 'text', text: `已设置文字对齐方式: ${params.justification}` }] };
143
+ }
144
+ return { content: [{ type: 'text', text: `设置失败: ${result}` }], isError: true };
145
+ } catch (e) {
146
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
147
+ }
148
+ }
149
+
150
+ export async function convertTextToMtext(params) {
151
+ if (!cad.connected) { await cad.connect(); }
152
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
153
+ try {
154
+ const handleList = params.handles
155
+ .map(h => `(setq ss (ssadd (handent "${escapeLispString(h)}") ss))`)
156
+ .join('\n');
157
+ const code = `(progn
158
+ (vl-load-com)
159
+ (setq ss (ssadd))
160
+ ${handleList}
161
+ (if (> (sslength ss) 0)
162
+ (progn (command "_.TXT2MTXT" ss "") "OK")
163
+ "NO_ENTITIES"
164
+ )
165
+ )`;
166
+ const result = await cad.sendCommandWithResult(code);
167
+ if (result === 'OK' || result === '"OK"') {
168
+ return { content: [{ type: 'text', text: `已转换 ${params.handles.length} 个单行文字为多行文字` }] };
169
+ }
170
+ return { content: [{ type: 'text', text: `转换失败: ${result}` }], isError: true };
171
+ } catch (e) {
172
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
173
+ }
174
+ }
175
+
176
+ export async function explodeText(params) {
177
+ if (!cad.connected) { await cad.connect(); }
178
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
179
+ try {
180
+ const code = `(progn
181
+ (vl-load-com)
182
+ (if (setq ent (handent "${escapeLispString(params.handle)}"))
183
+ (progn
184
+ (command "_.TXTEXP" ent "")
185
+ "OK"
186
+ )
187
+ "NOTFOUND"
188
+ )
189
+ )`;
190
+ const result = await cad.sendCommandWithResult(code);
191
+ if (result === 'OK' || result === '"OK"') {
192
+ return { content: [{ type: 'text', text: `已分解文字为线: ${params.handle}` }] };
193
+ }
194
+ return { content: [{ type: 'text', text: `分解失败: ${result}` }], isError: true };
195
+ } catch (e) {
196
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
197
+ }
198
+ }
@@ -0,0 +1,271 @@
1
+ import { cad } from '../cad.js';
2
+ import { escapeLispString } from '../handler-utils.js';
3
+
4
+ function toSafePoint(pt) {
5
+ const parts = (Array.isArray(pt) ? pt : String(pt).split(/[,\s]+/)).map(Number);
6
+ return parts.filter(n => !isNaN(n)).join(' ');
7
+ }
8
+
9
+ export async function createUcs(name, origin = '0,0,0', xAxis = '1,0,0', yAxis = '0,1,0') {
10
+ if (!cad.connected) { await cad.connect(); }
11
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
12
+
13
+ const code = `(progn
14
+ (vl-load-com)
15
+ (if (not (tblsearch "UCS" "${escapeLispString(name)}"))
16
+ (progn
17
+ (command "._UCS" "N" "${escapeLispString(name)}")
18
+ (command "._UCS" "${escapeLispString(name)}" "O" (list ${toSafePoint(origin)}))
19
+ (command "._UCS" "${escapeLispString(name)}" "X" (list ${toSafePoint(xAxis)}))
20
+ (command "._UCS" "${escapeLispString(name)}" "Y" (list ${toSafePoint(yAxis)}))
21
+ "CREATED"
22
+ )
23
+ "EXISTS"
24
+ )
25
+ )`;
26
+ try {
27
+ const result = await cad.sendCommandWithResult(code);
28
+ if (result === 'CREATED' || result === '"CREATED"') {
29
+ return { content: [{ type: 'text', text: `已创建 UCS: ${name}` }] };
30
+ }
31
+ if (result === 'EXISTS' || result === '"EXISTS"') {
32
+ return { content: [{ type: 'text', text: `UCS 已存在: ${name}` }], isError: true };
33
+ }
34
+ return { content: [{ type: 'text', text: `创建失败: ${result}` }], isError: true };
35
+ } catch (e) {
36
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
37
+ }
38
+ }
39
+
40
+ export async function setUcs(name) {
41
+ if (!cad.connected) { await cad.connect(); }
42
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
43
+
44
+ const code = `(progn
45
+ (vl-load-com)
46
+ (if (tblsearch "UCS" "${escapeLispString(name)}")
47
+ (progn
48
+ (command "._UCS" "R" "${escapeLispString(name)}")
49
+ "SET"
50
+ )
51
+ "NOTFOUND"
52
+ )
53
+ )`;
54
+ try {
55
+ const result = await cad.sendCommandWithResult(code);
56
+ if (result === 'SET' || result === '"SET"') {
57
+ return { content: [{ type: 'text', text: `已切换到 UCS: ${name}` }] };
58
+ }
59
+ return { content: [{ type: 'text', text: `UCS 不存在: ${name}` }], isError: true };
60
+ } catch (e) {
61
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
62
+ }
63
+ }
64
+
65
+ export async function listUcs() {
66
+ if (!cad.connected) { await cad.connect(); }
67
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
68
+
69
+ const code = `(progn
70
+ (vl-load-com)
71
+ (setq ucsList nil)
72
+ (while (setq u (tblnext "UCS" (null ucsList)))
73
+ (setq ucsList (cons (cdr (assoc 2 u)) ucsList))
74
+ )
75
+ (reverse ucsList)
76
+ )`;
77
+ try {
78
+ const result = await cad.sendCommandWithResult(code);
79
+ if (!result || result === 'nil') {
80
+ return { content: [{ type: 'text', text: '当前没有 UCS' }] };
81
+ }
82
+ return { content: [{ type: 'text', text: result }] };
83
+ } catch (e) {
84
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
85
+ }
86
+ }
87
+
88
+ export async function deleteUcs(name) {
89
+ if (!cad.connected) { await cad.connect(); }
90
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
91
+
92
+ const code = `(progn
93
+ (vl-load-com)
94
+ (if (tblsearch "UCS" "${escapeLispString(name)}")
95
+ (progn
96
+ (command "._UCS" "D" "${escapeLispString(name)}")
97
+ "DELETED"
98
+ )
99
+ "NOTFOUND"
100
+ )
101
+ )`;
102
+ try {
103
+ const result = await cad.sendCommandWithResult(code);
104
+ if (result === 'DELETED' || result === '"DELETED"') {
105
+ return { content: [{ type: 'text', text: `已删除 UCS: ${name}` }] };
106
+ }
107
+ return { content: [{ type: 'text', text: `UCS 不存在: ${name}` }], isError: true };
108
+ } catch (e) {
109
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
110
+ }
111
+ }
112
+
113
+ export async function getCurrentUcs() {
114
+ if (!cad.connected) { await cad.connect(); }
115
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
116
+
117
+ const code = `(progn
118
+ (vl-load-com)
119
+ (vla-get-activeutilities (vla-get-document (vla-get-application (vlax-get-acad-object))))
120
+ (vl-prin1-to-string (getvar "UCSNAME"))
121
+ )`;
122
+ try {
123
+ const result = await cad.sendCommandWithResult(code);
124
+ return { content: [{ type: 'text', text: result || '未命名' }] };
125
+ } catch (e) {
126
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
127
+ }
128
+ }
129
+
130
+ export async function createLayout(name) {
131
+ if (!cad.connected) { await cad.connect(); }
132
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
133
+
134
+ const code = `(progn
135
+ (vl-load-com)
136
+ (setq @layouts (layoutlist))
137
+ (if (member "${escapeLispString(name)}" @layouts)
138
+ "EXISTS"
139
+ (progn
140
+ (command "._LAYOUT" "N" "${escapeLispString(name)}")
141
+ "CREATED"
142
+ )
143
+ )
144
+ )`;
145
+ try {
146
+ const result = await cad.sendCommandWithResult(code);
147
+ if (result === 'CREATED' || result === '"CREATED"') {
148
+ return { content: [{ type: 'text', text: `已创建布局: ${name}` }] };
149
+ }
150
+ if (result === 'EXISTS' || result === '"EXISTS"') {
151
+ return { content: [{ type: 'text', text: `布局已存在: ${name}` }], isError: true };
152
+ }
153
+ return { content: [{ type: 'text', text: `创建失败: ${result}` }], isError: true };
154
+ } catch (e) {
155
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
156
+ }
157
+ }
158
+
159
+ export async function setLayout(name) {
160
+ if (!cad.connected) { await cad.connect(); }
161
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
162
+
163
+ const code = `(progn
164
+ (vl-load-com)
165
+ (setq @result "NOTFOUND")
166
+ (vlax-for layout (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
167
+ (if (= (vla-get-name layout) "${escapeLispString(name)}")
168
+ (progn
169
+ (vla-put-activelayout (vla-get-activedocument (vlax-get-acad-object)) layout)
170
+ (setq @result "SET")
171
+ )
172
+ )
173
+ )
174
+ @result
175
+ )`;
176
+ try {
177
+ const result = await cad.sendCommandWithResult(code);
178
+ if (result === 'SET' || result === '"SET"') {
179
+ return { content: [{ type: 'text', text: `已切换到布局: ${name}` }] };
180
+ }
181
+ return { content: [{ type: 'text', text: `布局不存在: ${name}` }], isError: true };
182
+ } catch (e) {
183
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
184
+ }
185
+ }
186
+
187
+ export async function listLayouts() {
188
+ if (!cad.connected) { await cad.connect(); }
189
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
190
+
191
+ const code = `(progn
192
+ (vl-load-com)
193
+ (vl-prin1-to-string (layoutlist))
194
+ )`;
195
+ try {
196
+ const result = await cad.sendCommandWithResult(code);
197
+ if (!result || result === 'nil') {
198
+ return { content: [{ type: 'text', text: '当前没有布局' }] };
199
+ }
200
+ return { content: [{ type: 'text', text: result }] };
201
+ } catch (e) {
202
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
203
+ }
204
+ }
205
+
206
+ export async function deleteLayout(name) {
207
+ if (!cad.connected) { await cad.connect(); }
208
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
209
+
210
+ if (name === 'Model' || name === '模型') {
211
+ return { content: [{ type: 'text', text: '无法删除模型空间' }], isError: true };
212
+ }
213
+
214
+ const code = `(progn
215
+ (vl-load-com)
216
+ (if (member "${escapeLispString(name)}" (layoutlist))
217
+ (progn
218
+ (command "._LAYOUT" "D" "${escapeLispString(name)}")
219
+ "DELETED"
220
+ )
221
+ "NOTFOUND"
222
+ )
223
+ )`;
224
+ try {
225
+ const result = await cad.sendCommandWithResult(code);
226
+ if (result === 'DELETED' || result === '"DELETED"') {
227
+ return { content: [{ type: 'text', text: `已删除布局: ${name}` }] };
228
+ }
229
+ return { content: [{ type: 'text', text: `布局不存在: ${name}` }], isError: true };
230
+ } catch (e) {
231
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
232
+ }
233
+ }
234
+
235
+ export async function getCurrentLayout() {
236
+ if (!cad.connected) { await cad.connect(); }
237
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
238
+
239
+ const code = `(vl-prin1-to-string (getvar "CTAB"))`;
240
+ try {
241
+ const result = await cad.sendCommandWithResult(code);
242
+ return { content: [{ type: 'text', text: result || 'Model' }] };
243
+ } catch (e) {
244
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
245
+ }
246
+ }
247
+
248
+ export async function renameLayout(oldName, newName) {
249
+ if (!cad.connected) { await cad.connect(); }
250
+ if (!cad.connected) return { content: [{ type: 'text', text: '未连接 CAD' }], isError: true };
251
+
252
+ const code = `(progn
253
+ (vl-load-com)
254
+ (if (member "${escapeLispString(oldName)}" (layoutlist))
255
+ (progn
256
+ (command ".-LAYOUT" "R" "${escapeLispString(oldName)}" "${escapeLispString(newName)}")
257
+ "RENAMED"
258
+ )
259
+ "NOTFOUND"
260
+ )
261
+ )`;
262
+ try {
263
+ const result = await cad.sendCommandWithResult(code);
264
+ if (result === 'RENAMED' || result === '"RENAMED"') {
265
+ return { content: [{ type: 'text', text: `已将布局 ${oldName} 重命名为 ${newName}` }] };
266
+ }
267
+ return { content: [{ type: 'text', text: `布局不存在: ${oldName}` }], isError: true };
268
+ } catch (e) {
269
+ return { content: [{ type: 'text', text: `错误: ${e.message}` }], isError: true };
270
+ }
271
+ }