@atlisp/mcp 1.8.26 → 1.8.28

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.
@@ -14806,10 +14806,16 @@ async function getHandlerModule(name) {
14806
14806
  await initHandlerModules();
14807
14807
  const loader = handlerModules[name];
14808
14808
  if (!loader) return null;
14809
- const mod = await loader();
14810
- moduleCache.set(name, mod);
14811
- log(`Handler module loaded: ${name}`);
14812
- return mod;
14809
+ try {
14810
+ const mod = await loader();
14811
+ moduleCache.set(name, mod);
14812
+ log(`Handler module loaded: ${name}`);
14813
+ return mod;
14814
+ } catch (e) {
14815
+ log(`Handler module load failed: ${name} - ${e.message}`);
14816
+ moduleCache.set(name, null);
14817
+ return null;
14818
+ }
14813
14819
  }
14814
14820
  async function initHandlerModules() {
14815
14821
  if (_handlerModulesInit) return;
Binary file
@@ -248,6 +248,7 @@ string encoding = d.encoding != null ? d.encoding.ToString() : "";
248
248
 
249
249
  int retries = 10;
250
250
  string result = "";
251
+ string rawBase64 = "";
251
252
  while (retries > 0 && !System.IO.File.Exists(tempFile)) {
252
253
  System.Threading.Thread.Sleep(200);
253
254
  retries--;
@@ -257,7 +258,7 @@ string encoding = d.encoding != null ? d.encoding.ToString() : "";
257
258
  while (retries > 0) {
258
259
  try {
259
260
  byte[] bytes = System.IO.File.ReadAllBytes(tempFile);
260
- string rawBase64 = System.Convert.ToBase64String(bytes);
261
+ rawBase64 = System.Convert.ToBase64String(bytes);
261
262
  System.Text.Encoding enc;
262
263
 
263
264
  if (!string.IsNullOrEmpty(encoding)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/mcp",
3
- "version": "1.8.26",
3
+ "version": "1.8.28",
4
4
  "description": "MCP Server for @lisp on CAD,support AutoCAD/GstarCAD/ZWCAD/BricsCAD or CAD platform compatible with AutoLISP",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,242 +0,0 @@
1
- import { cad } from '../cad.js';
2
- import { escapeLispString } from '../handler-utils.js';
3
-
4
- function ensureCad() {
5
- if (!cad.connected) throw new Error('未连接 CAD');
6
- }
7
-
8
- function esc(s) {
9
- return escapeLispString(String(s));
10
- }
11
-
12
- function buildFileList(files) {
13
- return files.map(f => `"${esc(f)}"`).join(' ');
14
- }
15
-
16
- export async function batchDocCheckStandards(args) {
17
- ensureCad();
18
- const { files, requiredLayers, forbiddenLayerPrefixes, requiredTextStyles, requiredDimStyles, maxLayerCount } = args;
19
- if (!files?.length) return { content: [{ type: 'text', text: '需要 files 参数' }], isError: true };
20
-
21
- const fileList = buildFileList(files);
22
- const reqLayers = (requiredLayers || []).map(l => `"${esc(l)}"`).join(' ');
23
- const forPrefixes = (forbiddenLayerPrefixes || []).map(p => `"${esc(p)}"`).join(' ');
24
- const reqTStyles = (requiredTextStyles || []).map(s => `"${esc(s)}"`).join(' ');
25
- const reqDStyles = (requiredDimStyles || []).map(s => `"${esc(s)}"`).join(' ');
26
-
27
- const lisp = `(progn
28
- (vl-load-com)
29
- (setq files (list ${fileList}))
30
- (setq req-layers (list ${reqLayers}))
31
- (setq for-prefixes (list ${forPrefixes}))
32
- (setq req-tstyles (list ${reqTStyles}))
33
- (setq req-dstyles (list ${reqDStyles}))
34
- (setq max-layer ${maxLayerCount || 9999})
35
- (setq all-reports (list))
36
- (foreach f files
37
- (setq report (list (cons "file" f) (cons "ok" T) (cons "issues" (list))))
38
- (if (findfile f)
39
- (progn
40
- (command "._OPEN" f)
41
- (setq issues (list))
42
- ;; check required layers
43
- (foreach l req-layers
44
- (if (not (tblsearch "LAYER" l))
45
- (setq issues (cons (list "missing_layer" (strcat "缺少必需图层: " l)) issues))))
46
- ;; check forbidden layer prefixes
47
- (setq all-layers (list))
48
- (setq i 0)
49
- (while (setq e (tblnext "LAYER" (if (= i 0) T nil)))
50
- (setq all-layers (cons (cdr (assoc 2 e)) all-layers))
51
- (setq i (1+ i)))
52
- (foreach p for-prefixes
53
- (foreach l all-layers
54
- (if (wcmatch (strcase l) (strcat (strcase p) "*"))
55
- (setq issues (cons (list "forbidden_layer" (strcat "禁止图层前缀: " l " 匹配 " p)) issues)))))
56
- ;; check layer count
57
- (if (> (length all-layers) max-layer)
58
- (setq issues (cons (list "too_many_layers" (strcat "图层数量 " (itoa (length all-layers)) " 超过限制 " (itoa max-layer))) issues)))
59
- ;; check required text styles
60
- (foreach s req-tstyles
61
- (if (not (tblsearch "STYLE" s))
62
- (setq issues (cons (list "missing_text_style" (strcat "缺少必需文字样式: " s)) issues))))
63
- ;; check required dim styles
64
- (foreach s req-dstyles
65
- (if (not (tblsearch "DIMSTYLE" s))
66
- (setq issues (cons (list "missing_dim_style" (strcat "缺少必需标注样式: " s)) issues))))
67
- (if issues
68
- (progn
69
- (setq report (cons (cons "ok" nil) report))
70
- (setq report (cons (cons "issues" issues) report)))
71
- )
72
- (command "_.CLOSE" "_N")
73
- )
74
- (setq report (cons (cons "ok" nil) (cons (cons "issues" (list (list "file_not_found" "文件不存在"))) report)))
75
- )
76
- (setq all-reports (cons report all-reports))
77
- )
78
- (princ all-reports)
79
- (princ))
80
- `;
81
-
82
- try {
83
- const raw = await cad.sendCommandWithResult(lisp);
84
- let reports;
85
- try {
86
- reports = typeof raw === 'string' ? JSON.parse(raw) : raw;
87
- } catch {
88
- reports = [{ file: 'parse_error', ok: false, issues: [{ type: 'parse_error', msg: String(raw).substring(0, 200) }] }];
89
- }
90
- return { content: [{ type: 'text', text: JSON.stringify(reports, null, 2) }] };
91
- } catch (e) {
92
- return { content: [{ type: 'text', text: `批量检查失败: ${e.message}` }], isError: true };
93
- }
94
- }
95
-
96
- export async function batchDocFindReplace(args) {
97
- ensureCad();
98
- const { files, pattern, replacement, caseSensitive, textTypes } = args;
99
- if (!files?.length) return { content: [{ type: 'text', text: '需要 files 参数' }], isError: true };
100
- if (!pattern) return { content: [{ type: 'text', text: '需要 pattern 参数' }], isError: true };
101
-
102
- const fileList = buildFileList(files);
103
- const caseFlag = caseSensitive ? 'nil' : 'T';
104
- const types = textTypes || ['ALL'];
105
- const textFilter = types.includes('ALL')
106
- ? '(cons 0 "TEXT,MTEXT")'
107
- : `(cons 0 "${types.join(',')}")`;
108
-
109
- const lisp = `(progn
110
- (vl-load-com)
111
- (setq files (list ${fileList}))
112
- (setq find-pat "${esc(pattern)}")
113
- (setq repl-text "${esc(replacement)}")
114
- (setq all-results (list))
115
- (foreach f files
116
- (setq result (list (cons "file" f) (cons "ok" T) (cons "count" 0)))
117
- (if (findfile f)
118
- (progn
119
- (command "._OPEN" f)
120
- (setq count 0)
121
- (setq ss (ssget "_X" ${textFilter}))
122
- (if ss
123
- (progn
124
- (setq i 0)
125
- (while (< i (sslength ss))
126
- (setq e (ssname ss i))
127
- (setq elist (entget e))
128
- (setq old (cdr (assoc 1 elist)))
129
- (if old
130
- (progn
131
- (setq new (vl-string-subst repl-text find-pat old))
132
- (if (/= new old)
133
- (progn
134
- (setq elist (subst (cons 1 new) (assoc 1 elist) elist))
135
- (entmod elist)
136
- (setq count (1+ count))
137
- )
138
- )
139
- )
140
- )
141
- (setq i (1+ i))
142
- )
143
- )
144
- )
145
- (setq result (cons (cons "count" count) result))
146
- (command "_.QSAVE")
147
- (command "_.CLOSE" "_Y")
148
- )
149
- (setq result (cons (cons "ok" nil) (cons (cons "error" "文件不存在") result)))
150
- )
151
- (setq all-results (cons result all-results))
152
- )
153
- (princ (vl-prin1-to-string all-results))
154
- (princ))
155
- `;
156
-
157
- try {
158
- const raw = await cad.sendCommandWithResult(lisp);
159
- let results;
160
- try {
161
- results = typeof raw === 'string' ? JSON.parse(raw) : raw;
162
- } catch {
163
- results = [{ file: 'parse_error', ok: false, error: String(raw).substring(0, 200) }];
164
- }
165
- const total = results.reduce((s, r) => s + (r.count || 0), 0);
166
- const text = `替换完成: 共处理 ${results.length} 个文件,${total} 处替换\n${JSON.stringify(results, null, 2)}`;
167
- return { content: [{ type: 'text', text }] };
168
- } catch (e) {
169
- return { content: [{ type: 'text', text: `批量替换失败: ${e.message}` }], isError: true };
170
- }
171
- }
172
-
173
- export async function batchDocCleanup(args) {
174
- ensureCad();
175
- const { files, purgeBlocks, purgeLayers, purgeStyles, runAudit, runOverkill, saveAndClose } = args;
176
- if (!files?.length) return { content: [{ type: 'text', text: '需要 files 参数' }], isError: true };
177
-
178
- const fileList = buildFileList(files);
179
- const doBlocks = purgeBlocks !== false;
180
- const doLayers = purgeLayers !== false;
181
- const doStyles = purgeStyles !== false;
182
- const doAudit = runAudit !== false;
183
-
184
- const lisp = `(progn
185
- (vl-load-com)
186
- (setq files (list ${fileList}))
187
- (setq all-results (list))
188
- (foreach f files
189
- (setq result (list (cons "file" f) (cons "ok" T)))
190
- (if (findfile f)
191
- (progn
192
- (command "._OPEN" f)
193
- (setq details (list))
194
- ;; audit
195
- (if ${doAudit}
196
- (progn
197
- (command "_.AUDIT" "_Y")
198
- (setq details (cons "audit_done" details))
199
- )
200
- )
201
- ;; purge
202
- (if ${doBlocks} (command "_.PURGE" "_B" "*" "_N"))
203
- (if ${doLayers} (command "_.PURGE" "_LA" "*" "_N"))
204
- (if ${doStyles} (command "_.PURGE" "_ST" "*" "_N"))
205
- (setq details (cons "purge_done" details))
206
- ;; overkill
207
- (if ${runOverkill}
208
- (progn
209
- (command "_.OVERKILL" (ssget "_X") "" "_Y")
210
- (setq details (cons "overkill_done" details))
211
- )
212
- )
213
- (setq result (cons (cons "actions" details) result))
214
- (if ${saveAndClose}
215
- (progn
216
- (command "_.QSAVE")
217
- (command "_.CLOSE" "_Y")
218
- )
219
- (command "_.CLOSE" "_N")
220
- )
221
- )
222
- (setq result (cons (cons "ok" nil) (cons (cons "error" "文件不存在") result)))
223
- )
224
- (setq all-results (cons result all-results))
225
- )
226
- (princ (vl-prin1-to-string all-results))
227
- (princ))
228
- `;
229
-
230
- try {
231
- const raw = await cad.sendCommandWithResult(lisp);
232
- let results;
233
- try {
234
- results = typeof raw === 'string' ? JSON.parse(raw) : raw;
235
- } catch {
236
- results = [{ file: 'parse_error', ok: false, error: String(raw).substring(0, 200) }];
237
- }
238
- return { content: [{ type: 'text', text: JSON.stringify(results, null, 2) }] };
239
- } catch (e) {
240
- return { content: [{ type: 'text', text: `批量清理失败: ${e.message}` }], isError: true };
241
- }
242
- }