@atlisp/mcp 1.8.27 → 1.8.29
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 +11 -5
- package/dist/cad-rothelper.dll +0 -0
- package/dist/config.js +1 -1
- package/package.json +1 -1
- package/dist/handlers/batch-doc-handlers.js +0 -242
package/dist/atlisp-mcp.js
CHANGED
|
@@ -116,7 +116,7 @@ var init_config = __esm({
|
|
|
116
116
|
TRANSPORT: z.enum(["http", "stdio", "ws"]).optional().default("http"),
|
|
117
117
|
MCP_API_KEY: z.string().optional().default(""),
|
|
118
118
|
ENABLE_SSE: z.coerce.boolean().optional().default(true),
|
|
119
|
-
MESSAGE_TIMEOUT: z.coerce.number().optional().default(
|
|
119
|
+
MESSAGE_TIMEOUT: z.coerce.number().optional().default(3e5),
|
|
120
120
|
HEARTBEAT_INTERVAL: z.coerce.number().optional().default(3e4),
|
|
121
121
|
BUSY_RETRIES: z.coerce.number().optional().default(10),
|
|
122
122
|
BUSY_DELAY: z.coerce.number().optional().default(500),
|
|
@@ -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
|
-
|
|
14810
|
-
|
|
14811
|
-
|
|
14812
|
-
|
|
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;
|
package/dist/cad-rothelper.dll
CHANGED
|
Binary file
|
package/dist/config.js
CHANGED
|
@@ -9,7 +9,7 @@ const envSchema = z.object({
|
|
|
9
9
|
TRANSPORT: z.enum(['http', 'stdio', 'ws']).optional().default('http'),
|
|
10
10
|
MCP_API_KEY: z.string().optional().default(''),
|
|
11
11
|
ENABLE_SSE: z.coerce.boolean().optional().default(true),
|
|
12
|
-
MESSAGE_TIMEOUT: z.coerce.number().optional().default(
|
|
12
|
+
MESSAGE_TIMEOUT: z.coerce.number().optional().default(300000),
|
|
13
13
|
HEARTBEAT_INTERVAL: z.coerce.number().optional().default(30000),
|
|
14
14
|
BUSY_RETRIES: z.coerce.number().optional().default(10),
|
|
15
15
|
BUSY_DELAY: z.coerce.number().optional().default(500),
|
package/package.json
CHANGED
|
@@ -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
|
-
}
|