@atlisp/mcp 1.8.23 → 1.8.26
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/README.md +52 -4
- package/dist/atlisp-mcp.js +1443 -857
- package/dist/cad-rothelper.dll +0 -0
- package/dist/cad-worker.js +239 -176
- package/dist/config.js +59 -56
- package/dist/handlers/batch-doc-handlers.js +242 -0
- package/dist/handlers/cad-handlers.js +10 -3
- package/dist/handlers/meta-handlers.js +70 -0
- package/dist/handlers/resource-cache.js +48 -16
- package/dist/handlers/resource-defs.js +3 -0
- package/dist/handlers/resource-handlers.js +123 -0
- package/dist/handlers/skill-handlers.js +152 -0
- package/dist/lisp-security.js +65 -0
- package/dist/prompts/definitions/workflow-batch-doc.json +27 -0
- package/package.json +3 -2
|
Binary file
|
package/dist/cad-worker.js
CHANGED
|
@@ -4,15 +4,55 @@ import process from 'process';
|
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import crypto from 'crypto';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
7
8
|
import { validateLispCodeWorker, checkParens } from './lisp-security.js';
|
|
8
9
|
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
const _dllPath = path.join(__dirname, '..', 'dist', 'cad-rothelper.dll');
|
|
13
|
+
|
|
14
|
+
function _loadDll(methodName) {
|
|
15
|
+
try {
|
|
16
|
+
return edge.func({
|
|
17
|
+
assemblyFile: _dllPath,
|
|
18
|
+
typeName: 'CadRotHelper.ConnectionManager',
|
|
19
|
+
methodName,
|
|
20
|
+
});
|
|
21
|
+
} catch (e) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function _loadEnum() {
|
|
27
|
+
try {
|
|
28
|
+
return edge.func({
|
|
29
|
+
assemblyFile: _dllPath,
|
|
30
|
+
typeName: 'CadRotHelper.RotEnumerator',
|
|
31
|
+
methodName: 'EnumerateAll',
|
|
32
|
+
});
|
|
33
|
+
} catch (e) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const _rotConnect = _loadDll('RotConnect');
|
|
39
|
+
const _rotDisconnect = _loadDll('RotDisconnect');
|
|
40
|
+
const _rotSendCmd = _loadDll('RotSendCommand');
|
|
41
|
+
const _rotSendResult = _loadDll('RotSendWithResult');
|
|
42
|
+
const _rotIsBusy = _loadDll('RotIsBusy');
|
|
43
|
+
const _rotHasDoc = _loadDll('RotHasDoc');
|
|
44
|
+
const _rotDocInfo = _loadDll('RotGetActiveDocInfo');
|
|
45
|
+
const _rotBringToFront = _loadDll('RotBringToFront');
|
|
46
|
+
const _rotNewDoc = _loadDll('RotNewDoc');
|
|
47
|
+
const _rotEnum = _loadEnum();
|
|
48
|
+
|
|
49
|
+
let _monikerSession = null;
|
|
50
|
+
|
|
9
51
|
const BUSY_RETRIES = parseInt(process.env.BUSY_RETRIES || '10', 10);
|
|
10
52
|
const BUSY_DELAY = parseInt(process.env.BUSY_DELAY || '500', 10);
|
|
11
53
|
|
|
12
|
-
// Lisp expression cache (hash -> compiled Lisp code)
|
|
13
54
|
const LISP_CACHE = new Map();
|
|
14
55
|
const LISP_CACHE_MAX = parseInt(process.env.LISP_CACHE_MAX || '500', 10);
|
|
15
|
-
|
|
16
56
|
const CACHE_TTL = parseInt(process.env.LISP_CACHE_TTL || '300000', 10);
|
|
17
57
|
|
|
18
58
|
function getCachedLisp(code) {
|
|
@@ -123,7 +163,7 @@ const cadLaunch = edge.func(function() {/*
|
|
|
123
163
|
}
|
|
124
164
|
} catch (Exception ex) {
|
|
125
165
|
System.Diagnostics.Debug.WriteLine("cadLaunch create " + progIds[i] + " error: " + ex.Message);
|
|
126
|
-
|
|
166
|
+
}
|
|
127
167
|
}
|
|
128
168
|
|
|
129
169
|
return new { success = false, error = "No CAD found" };
|
|
@@ -135,14 +175,14 @@ const cadSend = edge.func(function() {/*
|
|
|
135
175
|
try {
|
|
136
176
|
dynamic d = input;
|
|
137
177
|
string code = d.code.ToString();
|
|
138
|
-
|
|
139
|
-
|
|
178
|
+
string platform = d.platform.ToString();
|
|
179
|
+
string progId = platform == "BricsCAD" ? "BricscadApp.AcadApplication" : platform + ".Application";
|
|
140
180
|
dynamic cad = System.Runtime.InteropServices.Marshal.GetActiveObject(progId);
|
|
141
181
|
if (cad != null) {
|
|
142
182
|
dynamic doc = cad.ActiveDocument;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
183
|
+
if (doc != null) {
|
|
184
|
+
doc.SendCommand(code);
|
|
185
|
+
return new { success = true };
|
|
146
186
|
}
|
|
147
187
|
}
|
|
148
188
|
} catch (Exception ex) {
|
|
@@ -165,18 +205,16 @@ string encoding = d.encoding != null ? d.encoding.ToString() : "";
|
|
|
165
205
|
string codeHash = d.codeHash != null ? d.codeHash.ToString() : "";
|
|
166
206
|
bool cacheEnabled = d.cacheEnabled != null && d.cacheEnabled.ToString() == "True";
|
|
167
207
|
bool hasCacheKey = cacheEnabled && !string.IsNullOrEmpty(codeHash);
|
|
168
|
-
|
|
169
|
-
|
|
208
|
+
string progId = platform == "BricsCAD" ? "BricscadApp.AcadApplication" : platform + ".Application";
|
|
209
|
+
string tempDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "@lisp", "tmp");
|
|
170
210
|
System.IO.Directory.CreateDirectory(tempDir);
|
|
171
|
-
|
|
172
|
-
// 结果文件始终使用 GUID 命名(每次调用唯一)
|
|
211
|
+
|
|
173
212
|
tempFile = System.IO.Path.Combine(tempDir, "atlisp_result_" + System.Guid.NewGuid().ToString("N") + ".txt");
|
|
174
|
-
|
|
175
|
-
// 代码文件:启用缓存时使用 hash 命名,否则使用 GUID 命名
|
|
213
|
+
|
|
176
214
|
string fileKey = hasCacheKey ? codeHash : System.Guid.NewGuid().ToString("N");
|
|
177
215
|
userCodeFile = System.IO.Path.Combine(tempDir, "atlisp_user_" + fileKey + ".lsp");
|
|
178
216
|
lispFile = System.IO.Path.Combine(tempDir, "atlisp_code_" + fileKey + ".lsp");
|
|
179
|
-
|
|
217
|
+
|
|
180
218
|
bool useCachedUserCode = false;
|
|
181
219
|
if (hasCacheKey) {
|
|
182
220
|
if (System.IO.File.Exists(userCodeFile)) {
|
|
@@ -186,11 +224,11 @@ string encoding = d.encoding != null ? d.encoding.ToString() : "";
|
|
|
186
224
|
}
|
|
187
225
|
}
|
|
188
226
|
}
|
|
189
|
-
|
|
227
|
+
|
|
190
228
|
if (!useCachedUserCode) {
|
|
191
229
|
System.IO.File.WriteAllText(userCodeFile, code, System.Text.Encoding.GetEncoding(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ANSICodePage));
|
|
192
230
|
}
|
|
193
|
-
|
|
231
|
+
|
|
194
232
|
string lispCode = "(progn"
|
|
195
233
|
+ "(setq f(open \"" + tempFile.Replace("\\", "\\\\") + "\" \"w\"))"
|
|
196
234
|
+ "(setq r(vl-catch-all-apply '(lambda ()(load \"" + userCodeFile.Replace("\\", "\\\\") + "\"))))"
|
|
@@ -199,15 +237,15 @@ string encoding = d.encoding != null ? d.encoding.ToString() : "";
|
|
|
199
237
|
+ "(princ r f))"
|
|
200
238
|
+ "(close f)"
|
|
201
239
|
+ "(princ))";
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
240
|
+
|
|
241
|
+
System.IO.File.WriteAllText(lispFile, lispCode, System.Text.Encoding.GetEncoding(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ANSICodePage));
|
|
242
|
+
|
|
205
243
|
dynamic cad = System.Runtime.InteropServices.Marshal.GetActiveObject(progId);
|
|
206
244
|
if (cad != null) {
|
|
207
245
|
dynamic doc = cad.ActiveDocument;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
246
|
+
if (doc != null) {
|
|
247
|
+
doc.SendCommand("(load \"" + lispFile.Replace("\\", "\\\\") + "\")\n");
|
|
248
|
+
|
|
211
249
|
int retries = 10;
|
|
212
250
|
string result = "";
|
|
213
251
|
while (retries > 0 && !System.IO.File.Exists(tempFile)) {
|
|
@@ -219,8 +257,9 @@ string encoding = d.encoding != null ? d.encoding.ToString() : "";
|
|
|
219
257
|
while (retries > 0) {
|
|
220
258
|
try {
|
|
221
259
|
byte[] bytes = System.IO.File.ReadAllBytes(tempFile);
|
|
260
|
+
string rawBase64 = System.Convert.ToBase64String(bytes);
|
|
222
261
|
System.Text.Encoding enc;
|
|
223
|
-
|
|
262
|
+
|
|
224
263
|
if (!string.IsNullOrEmpty(encoding)) {
|
|
225
264
|
enc = System.Text.Encoding.GetEncoding(encoding);
|
|
226
265
|
} else {
|
|
@@ -239,13 +278,13 @@ string encoding = d.encoding != null ? d.encoding.ToString() : "";
|
|
|
239
278
|
}
|
|
240
279
|
}
|
|
241
280
|
}
|
|
242
|
-
|
|
281
|
+
|
|
243
282
|
result = enc.GetString(bytes).Trim();
|
|
244
|
-
|
|
283
|
+
|
|
245
284
|
if (result.StartsWith("ERROR:")) {
|
|
246
285
|
return new { success = false, error = result.Substring(6).Trim() };
|
|
247
286
|
}
|
|
248
|
-
|
|
287
|
+
|
|
249
288
|
try { System.IO.File.Delete(tempFile); } catch {}
|
|
250
289
|
try { System.IO.File.Delete(lispFile); } catch {}
|
|
251
290
|
if (!hasCacheKey) { try { if (System.IO.File.Exists(userCodeFile)) System.IO.File.Delete(userCodeFile); } catch {} }
|
|
@@ -256,9 +295,9 @@ string encoding = d.encoding != null ? d.encoding.ToString() : "";
|
|
|
256
295
|
}
|
|
257
296
|
}
|
|
258
297
|
if (!string.IsNullOrEmpty(result)) {
|
|
259
|
-
return new { success = true, result = result };
|
|
298
|
+
return new { success = true, result = result, rawBase64 = rawBase64 };
|
|
260
299
|
}
|
|
261
|
-
return new { success = true, result = "" };
|
|
300
|
+
return new { success = true, result = "", rawBase64 = rawBase64 };
|
|
262
301
|
}
|
|
263
302
|
return new { success = true, result = "" };
|
|
264
303
|
}
|
|
@@ -512,184 +551,208 @@ function computeCodeHash(code, cacheEnabled) {
|
|
|
512
551
|
return '';
|
|
513
552
|
}
|
|
514
553
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
return {
|
|
554
|
+
function dllCall(fn, args) {
|
|
555
|
+
return new Promise((resolve, reject) => {
|
|
556
|
+
if (!fn) return resolve({ success: false, error: 'DLL method not available' });
|
|
557
|
+
fn(args, (e, r) => {
|
|
558
|
+
if (e) reject(e);
|
|
559
|
+
else resolve(r);
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
async function monikerOrEdge(rotFn, edgeFn, args, platform) {
|
|
565
|
+
if (_monikerSession && rotFn) return await dllCall(rotFn, { key: _monikerSession, ...args });
|
|
566
|
+
return new Promise((resolve, reject) => {
|
|
567
|
+
edgeFn(platform || 'AutoCAD', (e, r) => {
|
|
568
|
+
if (e) reject(e);
|
|
569
|
+
else resolve(r);
|
|
570
|
+
});
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function validateCode(code) {
|
|
575
|
+
const parenCheck = checkParens(code);
|
|
576
|
+
if (!parenCheck.valid) {
|
|
577
|
+
return { valid: false, error: `括号错误: ${parenCheck.error} (位置 ${parenCheck.pos})` };
|
|
518
578
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const result = await new Promise((resolve, reject) => {
|
|
525
|
-
cadConnect({}, (e, r) => {
|
|
526
|
-
if (e) reject(e);
|
|
527
|
-
else resolve(r);
|
|
528
|
-
});
|
|
529
|
-
});
|
|
530
|
-
if (result && result.success) return result;
|
|
531
|
-
} catch (e) {
|
|
532
|
-
log('cadConnect failed: ' + e.message);
|
|
579
|
+
const securityLevel = process.env.SECURITY_LEVEL || 'strict';
|
|
580
|
+
if (securityLevel !== 'relaxed') {
|
|
581
|
+
const injectionCheck = validateLispCodeWorker(code);
|
|
582
|
+
if (!injectionCheck.valid) {
|
|
583
|
+
return { valid: false, error: `安全限制: ${injectionCheck.error}` };
|
|
533
584
|
}
|
|
534
|
-
return new Promise((resolve, reject) => {
|
|
535
|
-
cadLaunch({}, (e, r) => {
|
|
536
|
-
if (e) reject(e);
|
|
537
|
-
else resolve(r);
|
|
538
|
-
});
|
|
539
|
-
});
|
|
540
585
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
586
|
+
return { valid: true };
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
async function ensureDocument(platform) {
|
|
590
|
+
if (_monikerSession) return true;
|
|
591
|
+
const docCheck = await new Promise((resolve, reject) => {
|
|
592
|
+
cadHasDoc(platform || 'AutoCAD', (e, r) => {
|
|
593
|
+
if (e) reject(e);
|
|
594
|
+
else resolve(r);
|
|
547
595
|
});
|
|
596
|
+
});
|
|
597
|
+
return docCheck.hasDoc;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
async function executeWithRetry(fn, label) {
|
|
601
|
+
const maxRetries = 3;
|
|
602
|
+
let lastError = null;
|
|
603
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
604
|
+
const isBusy = await waitForIdle();
|
|
605
|
+
if (isBusy) {
|
|
606
|
+
try {
|
|
607
|
+
return await fn();
|
|
608
|
+
} catch (e) {
|
|
609
|
+
log(`${label} error: ${e.message}`);
|
|
610
|
+
lastError = e;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
await new Promise(r => setTimeout(r, 500));
|
|
548
614
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
});
|
|
615
|
+
return { success: false, error: lastError?.message || '发送失败' };
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
async function executeLisp(msg, withResult) {
|
|
619
|
+
if (!msg.code.endsWith('\n')) {
|
|
620
|
+
msg.code += '\n';
|
|
556
621
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
});
|
|
622
|
+
|
|
623
|
+
const validation = validateCode(msg.code);
|
|
624
|
+
if (!validation.valid) return validation;
|
|
625
|
+
|
|
626
|
+
if (!await ensureDocument(msg.platform)) {
|
|
627
|
+
return { success: false, error: 'No open document' };
|
|
564
628
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
const docCheck = await new Promise((resolve, reject) => {
|
|
570
|
-
cadHasDoc(msg.platform || 'AutoCAD', (e, r) => {
|
|
571
|
-
if (e) reject(e);
|
|
572
|
-
else resolve(r);
|
|
573
|
-
});
|
|
574
|
-
});
|
|
575
|
-
if (!docCheck.hasDoc) {
|
|
576
|
-
return { success: false, error: 'No open document' };
|
|
577
|
-
}
|
|
578
|
-
const parenCheck = checkParens(msg.code);
|
|
579
|
-
if (!parenCheck.valid) {
|
|
580
|
-
return { success: false, error: `括号错误: ${parenCheck.error} (位置 ${parenCheck.pos})` };
|
|
581
|
-
}
|
|
582
|
-
const securityLevel = process.env.SECURITY_LEVEL || 'strict';
|
|
583
|
-
if (securityLevel !== 'relaxed') {
|
|
584
|
-
const injectionCheck = validateLispCodeWorker(msg.code);
|
|
585
|
-
if (!injectionCheck.valid) {
|
|
586
|
-
return { success: false, error: `安全限制: ${injectionCheck.error}` };
|
|
587
|
-
}
|
|
629
|
+
|
|
630
|
+
if (_monikerSession) {
|
|
631
|
+
if (withResult || msg.code.length > 240) {
|
|
632
|
+
return await dllCall(_rotSendResult, { key: _monikerSession, code: msg.code, encoding: msg.encoding || '' });
|
|
588
633
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
634
|
+
return await dllCall(_rotSendCmd, { key: _monikerSession, code: msg.code });
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (withResult || msg.code.length > 255) {
|
|
638
|
+
const cacheEnabled = process.env.LONG_CODE_CACHE === '1';
|
|
639
|
+
const codeHash = computeCodeHash(msg.code, cacheEnabled);
|
|
640
|
+
log(`sendResult (${msg.code.length} chars, cache=${cacheEnabled}): ${msg.code.substring(0, 80)}...`);
|
|
641
|
+
return await executeWithRetry(async () => {
|
|
593
642
|
const r = await new Promise((resolve, reject) => {
|
|
594
|
-
cadSendWithResult({ code: msg.code, platform: msg.platform
|
|
643
|
+
cadSendWithResult({ code: msg.code, platform: msg.platform, encoding: msg.encoding || '', codeHash, cacheEnabled }, (e, r) => {
|
|
595
644
|
if (e) reject(e);
|
|
596
645
|
else resolve(r);
|
|
597
646
|
});
|
|
598
647
|
});
|
|
599
|
-
log(`
|
|
648
|
+
log(`sendResult result: ${JSON.stringify(r)}`);
|
|
600
649
|
return r;
|
|
601
|
-
}
|
|
602
|
-
const maxRetries = 3;
|
|
603
|
-
let lastError = null;
|
|
604
|
-
for (let i = 0; i < maxRetries; i++) {
|
|
605
|
-
const isBusy = await waitForIdle(msg.platform || 'AutoCAD');
|
|
606
|
-
if (isBusy) {
|
|
607
|
-
log(`send: ${msg.code}`);
|
|
608
|
-
try {
|
|
609
|
-
const r = await new Promise((resolve, reject) => {
|
|
610
|
-
cadSend({ code: msg.code, platform: msg.platform }, (e, r) => {
|
|
611
|
-
if (e) reject(e);
|
|
612
|
-
else resolve(r);
|
|
613
|
-
});
|
|
614
|
-
});
|
|
615
|
-
log(`send result: ${JSON.stringify(r)}`);
|
|
616
|
-
return r;
|
|
617
|
-
} catch (e) {
|
|
618
|
-
log(`send error: ${e.message}`);
|
|
619
|
-
lastError = e;
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
await new Promise(r => setTimeout(r, 500));
|
|
623
|
-
}
|
|
624
|
-
return { success: false, error: lastError?.message || '发送失败' };
|
|
650
|
+
}, 'sendResult');
|
|
625
651
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
652
|
+
|
|
653
|
+
log(`send: ${msg.code}`);
|
|
654
|
+
return await executeWithRetry(async () => {
|
|
655
|
+
const r = await new Promise((resolve, reject) => {
|
|
656
|
+
cadSend({ code: msg.code, platform: msg.platform }, (e, r) => {
|
|
629
657
|
if (e) reject(e);
|
|
630
658
|
else resolve(r);
|
|
631
659
|
});
|
|
632
660
|
});
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
const isBusy = await waitForIdle(msg.platform);
|
|
650
|
-
if (isBusy) {
|
|
651
|
-
log(`sendResult: ${msg.code}`);
|
|
652
|
-
try {
|
|
653
|
-
const r = await new Promise((resolve, reject) => {
|
|
654
|
-
cadSendWithResult({ code: msg.code, platform: msg.platform, encoding: msg.encoding || '', codeHash, cacheEnabled }, (e, r) => {
|
|
655
|
-
if (e) reject(e);
|
|
656
|
-
else resolve(r);
|
|
657
|
-
});
|
|
658
|
-
});
|
|
659
|
-
log(`sendResult result: ${JSON.stringify(r)}`);
|
|
660
|
-
return r;
|
|
661
|
-
} catch (e) {
|
|
662
|
-
log(`sendResult error: ${e.message}`);
|
|
663
|
-
lastErrorResult = e;
|
|
664
|
-
}
|
|
661
|
+
log(`send result: ${JSON.stringify(r)}`);
|
|
662
|
+
return r;
|
|
663
|
+
}, 'send');
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
const MESSAGE_HANDLERS = {
|
|
667
|
+
ping() {
|
|
668
|
+
return { pong: true };
|
|
669
|
+
},
|
|
670
|
+
|
|
671
|
+
async connect(msg) {
|
|
672
|
+
if (msg.moniker && _rotConnect) {
|
|
673
|
+
const result = await dllCall(_rotConnect, { key: msg.monikerKey, moniker: msg.moniker });
|
|
674
|
+
if (result && result.success) {
|
|
675
|
+
_monikerSession = msg.monikerKey;
|
|
676
|
+
return result;
|
|
665
677
|
}
|
|
666
|
-
|
|
678
|
+
return result;
|
|
667
679
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
680
|
+
if (msg.platform) {
|
|
681
|
+
return await connectToPlatform(msg.platform);
|
|
682
|
+
}
|
|
683
|
+
try {
|
|
684
|
+
const result = await new Promise((resolve, reject) => {
|
|
685
|
+
cadConnect({}, (e, r) => {
|
|
686
|
+
if (e) reject(e);
|
|
687
|
+
else resolve(r);
|
|
688
|
+
});
|
|
675
689
|
});
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
690
|
+
if (result && result.success) return result;
|
|
691
|
+
} catch (e) {
|
|
692
|
+
log('cadConnect failed: ' + e.message);
|
|
693
|
+
}
|
|
679
694
|
return new Promise((resolve, reject) => {
|
|
680
|
-
|
|
695
|
+
cadLaunch({}, (e, r) => {
|
|
681
696
|
if (e) reject(e);
|
|
682
697
|
else resolve(r);
|
|
683
698
|
});
|
|
684
699
|
});
|
|
685
|
-
}
|
|
686
|
-
|
|
700
|
+
},
|
|
701
|
+
|
|
702
|
+
async disconnect() {
|
|
703
|
+
if (_monikerSession && _rotDisconnect) {
|
|
704
|
+
await dllCall(_rotDisconnect, { key: _monikerSession });
|
|
705
|
+
}
|
|
706
|
+
_monikerSession = null;
|
|
707
|
+
return { success: true };
|
|
708
|
+
},
|
|
709
|
+
|
|
710
|
+
async hasdoc(msg) {
|
|
711
|
+
return await monikerOrEdge(_rotHasDoc, cadHasDoc, {}, msg.platform);
|
|
712
|
+
},
|
|
713
|
+
|
|
714
|
+
async newdoc(msg) {
|
|
715
|
+
return await monikerOrEdge(_rotNewDoc, cadNewDoc, {}, msg.platform);
|
|
716
|
+
},
|
|
717
|
+
|
|
718
|
+
async bringToFront(msg) {
|
|
719
|
+
return await monikerOrEdge(_rotBringToFront, cadBringToFront, {}, msg.platform);
|
|
720
|
+
},
|
|
721
|
+
|
|
722
|
+
async send(msg) {
|
|
723
|
+
return await executeLisp(msg, false);
|
|
724
|
+
},
|
|
725
|
+
|
|
726
|
+
async sendResult(msg) {
|
|
727
|
+
return await executeLisp(msg, true);
|
|
728
|
+
},
|
|
729
|
+
|
|
730
|
+
async isBusy(msg) {
|
|
731
|
+
return await monikerOrEdge(_rotIsBusy, cadIsBusy, {}, msg.platform);
|
|
732
|
+
},
|
|
733
|
+
|
|
734
|
+
async getActiveDocInfo(msg) {
|
|
735
|
+
return await monikerOrEdge(_rotDocInfo, cadGetActiveDocInfo, {}, msg.platform);
|
|
736
|
+
},
|
|
737
|
+
|
|
738
|
+
async startMonitor(msg) {
|
|
739
|
+
if (_monikerSession) {
|
|
740
|
+
return { success: false, error: 'startMonitor not supported for moniker connections' };
|
|
741
|
+
}
|
|
687
742
|
return new Promise((resolve, reject) => {
|
|
688
743
|
cadStartMonitor(msg.platform || 'AutoCAD', (e, r) => {
|
|
689
744
|
if (e) reject(e);
|
|
690
745
|
else resolve(r);
|
|
691
746
|
});
|
|
692
747
|
});
|
|
693
|
-
}
|
|
694
|
-
|
|
748
|
+
},
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
export async function handleMessage(msg) {
|
|
752
|
+
const handler = MESSAGE_HANDLERS[msg.type];
|
|
753
|
+
if (!handler) return { error: 'unknown message type' };
|
|
754
|
+
return await handler(msg);
|
|
695
755
|
}
|
|
756
|
+
|
|
757
|
+
// Exported for testing
|
|
758
|
+
export { validateCode, computeCodeHash, getCachedLisp, setCachedLisp, MESSAGE_HANDLERS, executeLisp };
|