@atlisp/mcp 1.4.3 → 1.4.4
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 +283 -220
- package/package.json +1 -1
package/dist/atlisp-mcp.js
CHANGED
|
@@ -36,7 +36,8 @@ var SessionTransport = class {
|
|
|
36
36
|
this._started = true;
|
|
37
37
|
}
|
|
38
38
|
async send(message) {
|
|
39
|
-
if (this._closed)
|
|
39
|
+
if (this._closed)
|
|
40
|
+
return;
|
|
40
41
|
if (this._pendingRequest) {
|
|
41
42
|
const { resolve, reject, timeout } = this._pendingRequest;
|
|
42
43
|
clearTimeout(timeout);
|
|
@@ -45,7 +46,8 @@ var SessionTransport = class {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
async close() {
|
|
48
|
-
if (this._closed)
|
|
49
|
+
if (this._closed)
|
|
50
|
+
return;
|
|
49
51
|
this._closed = true;
|
|
50
52
|
if (this._pendingRequest) {
|
|
51
53
|
const { reject, timeout } = this._pendingRequest;
|
|
@@ -119,7 +121,7 @@ var FILE_EXTENSIONS = {
|
|
|
119
121
|
"BricsCAD": [".des"]
|
|
120
122
|
};
|
|
121
123
|
var SERVER_NAME = "atlisp-mcp-server";
|
|
122
|
-
var SERVER_VERSION = "1.4.
|
|
124
|
+
var SERVER_VERSION = "1.4.4";
|
|
123
125
|
var MOCK_PACKAGES = [
|
|
124
126
|
{ name: "base", description: "\u57FA\u7840\u51FD\u6570\u5E93", version: "1.0.0" },
|
|
125
127
|
{ name: "at-pm", description: "\u5DE5\u7A0B\u9879\u76EE\u7BA1\u7406", version: "2.1.0" },
|
|
@@ -237,7 +239,8 @@ function setupStdoutHandler(w) {
|
|
|
237
239
|
const lines = buffer.split("\n");
|
|
238
240
|
buffer = lines.pop() || "";
|
|
239
241
|
for (const line of lines) {
|
|
240
|
-
if (!line.trim())
|
|
242
|
+
if (!line.trim())
|
|
243
|
+
continue;
|
|
241
244
|
try {
|
|
242
245
|
const result = JSON.parse(line);
|
|
243
246
|
const rid = result.requestId;
|
|
@@ -263,7 +266,8 @@ function setupStdoutHandler(w) {
|
|
|
263
266
|
}
|
|
264
267
|
function getWorker(force = false) {
|
|
265
268
|
if (!worker || !worker.connected || force) {
|
|
266
|
-
if (worker)
|
|
269
|
+
if (worker)
|
|
270
|
+
worker.kill();
|
|
267
271
|
worker = spawn("node", [workerPath], {
|
|
268
272
|
stdio: ["pipe", "pipe", "pipe"]
|
|
269
273
|
});
|
|
@@ -271,7 +275,8 @@ function getWorker(force = false) {
|
|
|
271
275
|
const w = worker;
|
|
272
276
|
w.on("exit", (code) => {
|
|
273
277
|
console.error("worker exited with code:", code);
|
|
274
|
-
if (w !== worker)
|
|
278
|
+
if (w !== worker)
|
|
279
|
+
return;
|
|
275
280
|
w.connected = false;
|
|
276
281
|
for (const [id, { reject, timeout }] of pendingRequests) {
|
|
277
282
|
clearTimeout(timeout);
|
|
@@ -292,7 +297,8 @@ function getWorker(force = false) {
|
|
|
292
297
|
return worker;
|
|
293
298
|
}
|
|
294
299
|
function startHeartbeat() {
|
|
295
|
-
if (heartbeatTimer)
|
|
300
|
+
if (heartbeatTimer)
|
|
301
|
+
clearInterval(heartbeatTimer);
|
|
296
302
|
heartbeatTimer = setInterval(async () => {
|
|
297
303
|
try {
|
|
298
304
|
const result = await sendMessage({ type: "ping" });
|
|
@@ -337,7 +343,8 @@ var CadConnection = class {
|
|
|
337
343
|
return process.platform === "win32";
|
|
338
344
|
}
|
|
339
345
|
async connect(platform = null) {
|
|
340
|
-
if (!this.isAvailable())
|
|
346
|
+
if (!this.isAvailable())
|
|
347
|
+
return false;
|
|
341
348
|
try {
|
|
342
349
|
const msg = platform ? { type: "connect", platform } : { type: "connect" };
|
|
343
350
|
const result = await sendMessage(msg);
|
|
@@ -354,13 +361,16 @@ var CadConnection = class {
|
|
|
354
361
|
return false;
|
|
355
362
|
}
|
|
356
363
|
async sendCommand(code) {
|
|
357
|
-
if (!this.connected)
|
|
364
|
+
if (!this.connected)
|
|
365
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
358
366
|
const result = await sendMessage({ type: "send", code, platform: _platform });
|
|
359
|
-
if (result.success)
|
|
367
|
+
if (result.success)
|
|
368
|
+
return true;
|
|
360
369
|
throw new Error(result.error || "\u53D1\u9001\u5931\u8D25");
|
|
361
370
|
}
|
|
362
371
|
async sendCommandWithResult(code, encoding = null) {
|
|
363
|
-
if (!this.connected)
|
|
372
|
+
if (!this.connected)
|
|
373
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
364
374
|
const result = await sendMessage({ type: "sendResult", code, platform: _platform, encoding: encoding || "" });
|
|
365
375
|
if (result.success) {
|
|
366
376
|
return result.result || "";
|
|
@@ -374,7 +384,8 @@ var CadConnection = class {
|
|
|
374
384
|
return this.product;
|
|
375
385
|
}
|
|
376
386
|
async isBusy() {
|
|
377
|
-
if (!this.connected)
|
|
387
|
+
if (!this.connected)
|
|
388
|
+
return false;
|
|
378
389
|
try {
|
|
379
390
|
const result = await sendMessage({ type: "isBusy", platform: _platform });
|
|
380
391
|
return result && result.isBusy;
|
|
@@ -383,7 +394,8 @@ var CadConnection = class {
|
|
|
383
394
|
}
|
|
384
395
|
}
|
|
385
396
|
async hasDoc() {
|
|
386
|
-
if (!this.connected)
|
|
397
|
+
if (!this.connected)
|
|
398
|
+
return { hasDoc: false, docCount: 0 };
|
|
387
399
|
try {
|
|
388
400
|
const result = await sendMessage({ type: "hasdoc", platform: _platform });
|
|
389
401
|
return result || { hasDoc: false, docCount: 0 };
|
|
@@ -392,7 +404,8 @@ var CadConnection = class {
|
|
|
392
404
|
}
|
|
393
405
|
}
|
|
394
406
|
async newDoc() {
|
|
395
|
-
if (!this.connected)
|
|
407
|
+
if (!this.connected)
|
|
408
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
396
409
|
try {
|
|
397
410
|
const result = await sendMessage({ type: "newdoc", platform: _platform });
|
|
398
411
|
return result && result.success;
|
|
@@ -401,7 +414,8 @@ var CadConnection = class {
|
|
|
401
414
|
}
|
|
402
415
|
}
|
|
403
416
|
async bringToFront() {
|
|
404
|
-
if (!this.connected)
|
|
417
|
+
if (!this.connected)
|
|
418
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
405
419
|
try {
|
|
406
420
|
const result = await sendMessage({ type: "bringToFront", platform: _platform });
|
|
407
421
|
return result && result.success;
|
|
@@ -410,7 +424,8 @@ var CadConnection = class {
|
|
|
410
424
|
}
|
|
411
425
|
}
|
|
412
426
|
async getInfo() {
|
|
413
|
-
if (!this.connected)
|
|
427
|
+
if (!this.connected)
|
|
428
|
+
return "CAD \u672A\u8FDE\u63A5";
|
|
414
429
|
return `Platform: ${this.product}, Version: ${this.version}, Status: Connected`;
|
|
415
430
|
}
|
|
416
431
|
async disconnect() {
|
|
@@ -447,9 +462,11 @@ var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
|
447
462
|
var MAX_LOG_FILES = 5;
|
|
448
463
|
var stream = null;
|
|
449
464
|
function rotateLog() {
|
|
450
|
-
if (!fs.existsSync(DEBUG_FILE))
|
|
465
|
+
if (!fs.existsSync(DEBUG_FILE))
|
|
466
|
+
return;
|
|
451
467
|
const stat = fs.statSync(DEBUG_FILE);
|
|
452
|
-
if (stat.size < MAX_LOG_SIZE)
|
|
468
|
+
if (stat.size < MAX_LOG_SIZE)
|
|
469
|
+
return;
|
|
453
470
|
if (stream) {
|
|
454
471
|
stream.end();
|
|
455
472
|
stream = null;
|
|
@@ -511,7 +528,8 @@ async function evalLisp(code, withResult = false, encoding = null) {
|
|
|
511
528
|
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
512
529
|
}
|
|
513
530
|
const trimmed = (code || "").trim();
|
|
514
|
-
if (!trimmed)
|
|
531
|
+
if (!trimmed)
|
|
532
|
+
return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
|
|
515
533
|
try {
|
|
516
534
|
if (withResult) {
|
|
517
535
|
const result = await cad.sendCommandWithResult(trimmed, encoding);
|
|
@@ -531,14 +549,17 @@ async function getCadInfo() {
|
|
|
531
549
|
if (!cad.connected) {
|
|
532
550
|
await cad.connect();
|
|
533
551
|
}
|
|
534
|
-
if (!cad.connected)
|
|
552
|
+
if (!cad.connected)
|
|
553
|
+
return { content: [{ type: "text", text: "CAD \u672A\u8FDE\u63A5" }] };
|
|
535
554
|
const info = await cad.getInfo();
|
|
536
555
|
return { content: [{ type: "text", text: info }] };
|
|
537
556
|
}
|
|
538
557
|
async function atCommand(command) {
|
|
539
|
-
if (!cad.connected)
|
|
558
|
+
if (!cad.connected)
|
|
559
|
+
return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
|
|
540
560
|
const trimmed = (command || "").trim();
|
|
541
|
-
if (!trimmed)
|
|
561
|
+
if (!trimmed)
|
|
562
|
+
return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
|
|
542
563
|
await cad.sendCommand(trimmed + "\n");
|
|
543
564
|
return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001\u547D\u4EE4" }] };
|
|
544
565
|
}
|
|
@@ -546,7 +567,8 @@ async function newDocument() {
|
|
|
546
567
|
if (!cad.connected) {
|
|
547
568
|
await cad.connect();
|
|
548
569
|
}
|
|
549
|
-
if (!cad.connected)
|
|
570
|
+
if (!cad.connected)
|
|
571
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
550
572
|
const result = await cad.newDoc();
|
|
551
573
|
if (result) {
|
|
552
574
|
return { content: [{ type: "text", text: "\u5DF2\u5728 CAD \u4E2D\u65B0\u5EFA\u7A7A\u767D\u6587\u6863" }] };
|
|
@@ -557,7 +579,8 @@ async function bringToFront() {
|
|
|
557
579
|
if (!cad.connected) {
|
|
558
580
|
await cad.connect();
|
|
559
581
|
}
|
|
560
|
-
if (!cad.connected)
|
|
582
|
+
if (!cad.connected)
|
|
583
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
561
584
|
const result = await cad.bringToFront();
|
|
562
585
|
if (result) {
|
|
563
586
|
return { content: [{ type: "text", text: "\u5DF2\u5C06 CAD \u7A97\u53E3\u5207\u6362\u5230\u524D\u53F0" }] };
|
|
@@ -568,7 +591,8 @@ async function installAtlisp() {
|
|
|
568
591
|
if (!cad.connected) {
|
|
569
592
|
await cad.connect();
|
|
570
593
|
}
|
|
571
|
-
if (!cad.connected)
|
|
594
|
+
if (!cad.connected)
|
|
595
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
572
596
|
const installCode = `(progn(vl-load-com)(setq s strcat h "http" o(vlax-create-object (s"win"h".win"h"request.5.1"))v vlax-invoke e eval r read)(v o'open "get" (s h"://atlisp.""cn/@"):vlax-true)(v o'send)(v o'WaitforResponse 1000)(e(r(vlax-get-property o'ResponseText))))`;
|
|
573
597
|
await cad.sendCommand(installCode + "\n");
|
|
574
598
|
return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001 @lisp \u5B89\u88C5\u4EE3\u7801\u5230 CAD" }] };
|
|
@@ -577,10 +601,12 @@ async function listFunctionsInCad() {
|
|
|
577
601
|
if (!cad.connected) {
|
|
578
602
|
await cad.connect();
|
|
579
603
|
}
|
|
580
|
-
if (!cad.connected)
|
|
604
|
+
if (!cad.connected)
|
|
605
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
581
606
|
try {
|
|
582
607
|
const result = await cad.sendCommandWithResult("(atoms-family 0)", null);
|
|
583
|
-
if (result)
|
|
608
|
+
if (result)
|
|
609
|
+
return { content: [{ type: "text", text: result }] };
|
|
584
610
|
return { content: [{ type: "text", text: "CAD \u51FD\u6570\u5217\u8868\u4E3A\u7A7A" }] };
|
|
585
611
|
} catch (e) {
|
|
586
612
|
return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
|
|
@@ -635,7 +661,8 @@ async function initAtlisp() {
|
|
|
635
661
|
if (!cad.connected) {
|
|
636
662
|
await cad.connect();
|
|
637
663
|
}
|
|
638
|
-
if (!cad.connected)
|
|
664
|
+
if (!cad.connected)
|
|
665
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
639
666
|
const code = `(if (null @::load-module)
|
|
640
667
|
(progn
|
|
641
668
|
(vl-load-com)
|
|
@@ -675,12 +702,15 @@ async function fetchPackages() {
|
|
|
675
702
|
return cachedPackages || MOCK_PACKAGES;
|
|
676
703
|
}
|
|
677
704
|
function flattenPackages(data) {
|
|
678
|
-
if (Array.isArray(data))
|
|
679
|
-
|
|
705
|
+
if (Array.isArray(data))
|
|
706
|
+
return data;
|
|
707
|
+
if (data && Array.isArray(data.packages))
|
|
708
|
+
return data.packages;
|
|
680
709
|
return [];
|
|
681
710
|
}
|
|
682
711
|
async function listPackages() {
|
|
683
|
-
if (!cad.connected)
|
|
712
|
+
if (!cad.connected)
|
|
713
|
+
await cad.connect();
|
|
684
714
|
if (!cad.connected) {
|
|
685
715
|
const data2 = await fetchPackages();
|
|
686
716
|
const items2 = flattenPackages(data2);
|
|
@@ -688,7 +718,8 @@ async function listPackages() {
|
|
|
688
718
|
return { content: [{ type: "text", text: text2 }] };
|
|
689
719
|
}
|
|
690
720
|
const result = await cad.sendCommandWithResult("(@::package-list-in-local)");
|
|
691
|
-
if (result && result !== "nil")
|
|
721
|
+
if (result && result !== "nil")
|
|
722
|
+
return { content: [{ type: "text", text: result }] };
|
|
692
723
|
const data = await fetchPackages();
|
|
693
724
|
const items = flattenPackages(data);
|
|
694
725
|
const text = items.length ? `\u4ECE\u6CE8\u518C\u8868\u83B7\u53D6\u7684 @lisp \u5305:
|
|
@@ -708,10 +739,12 @@ async function searchPackages(query) {
|
|
|
708
739
|
for (const p of items) {
|
|
709
740
|
const name = (p.name || "").toLowerCase();
|
|
710
741
|
const desc = (p.description || "").toLowerCase();
|
|
711
|
-
if (name.includes(q) || desc.includes(q))
|
|
742
|
+
if (name.includes(q) || desc.includes(q))
|
|
743
|
+
results.push(p);
|
|
712
744
|
}
|
|
713
745
|
} else {
|
|
714
|
-
for (const p of items)
|
|
746
|
+
for (const p of items)
|
|
747
|
+
results.push(p);
|
|
715
748
|
}
|
|
716
749
|
if (results.length === 0) {
|
|
717
750
|
return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5305\u542B "${query}" \u7684\u5305` }] };
|
|
@@ -763,7 +796,8 @@ function writeCacheToDisk(data) {
|
|
|
763
796
|
}
|
|
764
797
|
async function fetchFunctions() {
|
|
765
798
|
const diskCache = readCacheFromDisk();
|
|
766
|
-
if (diskCache)
|
|
799
|
+
if (diskCache)
|
|
800
|
+
return diskCache;
|
|
767
801
|
try {
|
|
768
802
|
const response = await fetch(FUNCTIONS_URL, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
769
803
|
if (response.ok) {
|
|
@@ -783,7 +817,8 @@ async function getFunctionUsage(funcName, packageName) {
|
|
|
783
817
|
if (data) {
|
|
784
818
|
const funcs = Object.values(data.all_functions || {});
|
|
785
819
|
const func = funcs.find((f2) => f2.name === funcName || f2.name === `${packageName}:${funcName}`);
|
|
786
|
-
if (func)
|
|
820
|
+
if (func)
|
|
821
|
+
results.push(func);
|
|
787
822
|
}
|
|
788
823
|
if (results.length === 0 && FUNCTIONS_DIR) {
|
|
789
824
|
try {
|
|
@@ -792,7 +827,8 @@ async function getFunctionUsage(funcName, packageName) {
|
|
|
792
827
|
const raw = fs2.readFileSync(path3.join(FUNCTIONS_DIR, file), "utf-8");
|
|
793
828
|
const data2 = JSON.parse(raw);
|
|
794
829
|
const func = data2.functions?.find((f2) => f2.name === funcName);
|
|
795
|
-
if (func)
|
|
830
|
+
if (func)
|
|
831
|
+
results.push(func);
|
|
796
832
|
}
|
|
797
833
|
} catch {
|
|
798
834
|
}
|
|
@@ -886,11 +922,14 @@ function clearCache(uri) {
|
|
|
886
922
|
}
|
|
887
923
|
}
|
|
888
924
|
function parseLispList(str) {
|
|
889
|
-
if (!str || typeof str !== "string")
|
|
925
|
+
if (!str || typeof str !== "string")
|
|
926
|
+
return null;
|
|
890
927
|
const trimmed = str.trim();
|
|
891
|
-
if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
|
|
928
|
+
if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
|
|
929
|
+
return null;
|
|
892
930
|
const content = trimmed.slice(1, -1).trim();
|
|
893
|
-
if (!content)
|
|
931
|
+
if (!content)
|
|
932
|
+
return [];
|
|
894
933
|
const result = [];
|
|
895
934
|
let depth = 0;
|
|
896
935
|
let current = "";
|
|
@@ -932,32 +971,44 @@ function parseLispList(str) {
|
|
|
932
971
|
}
|
|
933
972
|
current += ch;
|
|
934
973
|
}
|
|
935
|
-
if (current.trim())
|
|
974
|
+
if (current.trim())
|
|
975
|
+
result.push(current.trim());
|
|
936
976
|
return result.map((item) => {
|
|
937
977
|
const t = item.trim();
|
|
938
|
-
if (t === "nil")
|
|
939
|
-
|
|
940
|
-
if (t === "
|
|
978
|
+
if (t === "nil")
|
|
979
|
+
return null;
|
|
980
|
+
if (t === "t")
|
|
981
|
+
return true;
|
|
982
|
+
if (t === "T")
|
|
983
|
+
return true;
|
|
941
984
|
const num = Number(t);
|
|
942
|
-
if (!isNaN(num) && t !== "")
|
|
943
|
-
|
|
985
|
+
if (!isNaN(num) && t !== "")
|
|
986
|
+
return num;
|
|
987
|
+
if (t.startsWith('"') && t.endsWith('"'))
|
|
988
|
+
return t.slice(1, -1);
|
|
944
989
|
return t;
|
|
945
990
|
});
|
|
946
991
|
}
|
|
947
992
|
function parseLispRecursive(str) {
|
|
948
|
-
if (!str || typeof str !== "string")
|
|
993
|
+
if (!str || typeof str !== "string")
|
|
994
|
+
return null;
|
|
949
995
|
str = str.trim();
|
|
950
|
-
if (!str)
|
|
996
|
+
if (!str)
|
|
997
|
+
return null;
|
|
951
998
|
let pos = 0;
|
|
952
999
|
function skipWs() {
|
|
953
|
-
while (pos < str.length && /\s/.test(str[pos]))
|
|
1000
|
+
while (pos < str.length && /\s/.test(str[pos]))
|
|
1001
|
+
pos++;
|
|
954
1002
|
}
|
|
955
1003
|
function parseValue() {
|
|
956
1004
|
skipWs();
|
|
957
|
-
if (pos >= str.length)
|
|
1005
|
+
if (pos >= str.length)
|
|
1006
|
+
return null;
|
|
958
1007
|
const ch = str[pos];
|
|
959
|
-
if (ch === "(")
|
|
960
|
-
|
|
1008
|
+
if (ch === "(")
|
|
1009
|
+
return parseList();
|
|
1010
|
+
if (ch === '"')
|
|
1011
|
+
return parseString();
|
|
961
1012
|
if (ch === "'") {
|
|
962
1013
|
pos++;
|
|
963
1014
|
return parseValue();
|
|
@@ -970,11 +1021,16 @@ function parseLispRecursive(str) {
|
|
|
970
1021
|
while (pos < str.length && str[pos] !== '"') {
|
|
971
1022
|
if (str[pos] === "\\" && pos + 1 < str.length) {
|
|
972
1023
|
pos++;
|
|
973
|
-
if (str[pos] === '"')
|
|
974
|
-
|
|
975
|
-
else if (str[pos] === "
|
|
976
|
-
|
|
977
|
-
else
|
|
1024
|
+
if (str[pos] === '"')
|
|
1025
|
+
r += '"';
|
|
1026
|
+
else if (str[pos] === "n")
|
|
1027
|
+
r += "\n";
|
|
1028
|
+
else if (str[pos] === "t")
|
|
1029
|
+
r += " ";
|
|
1030
|
+
else if (str[pos] === "\\")
|
|
1031
|
+
r += "\\";
|
|
1032
|
+
else
|
|
1033
|
+
r += str[pos];
|
|
978
1034
|
} else {
|
|
979
1035
|
r += str[pos];
|
|
980
1036
|
}
|
|
@@ -985,12 +1041,16 @@ function parseLispRecursive(str) {
|
|
|
985
1041
|
}
|
|
986
1042
|
function parseAtom() {
|
|
987
1043
|
const start = pos;
|
|
988
|
-
while (pos < str.length && !/\s/.test(str[pos]) && str[pos] !== ")" && str[pos] !== "(")
|
|
1044
|
+
while (pos < str.length && !/\s/.test(str[pos]) && str[pos] !== ")" && str[pos] !== "(")
|
|
1045
|
+
pos++;
|
|
989
1046
|
const atom = str.slice(start, pos);
|
|
990
|
-
if (atom === "nil" || atom === "NIL")
|
|
991
|
-
|
|
1047
|
+
if (atom === "nil" || atom === "NIL")
|
|
1048
|
+
return null;
|
|
1049
|
+
if (atom === "t" || atom === "T")
|
|
1050
|
+
return true;
|
|
992
1051
|
const num = Number(atom);
|
|
993
|
-
if (!isNaN(num) && atom !== "")
|
|
1052
|
+
if (!isNaN(num) && atom !== "")
|
|
1053
|
+
return num;
|
|
994
1054
|
return atom;
|
|
995
1055
|
}
|
|
996
1056
|
function parseList() {
|
|
@@ -998,13 +1058,15 @@ function parseLispRecursive(str) {
|
|
|
998
1058
|
const items = [];
|
|
999
1059
|
while (pos < str.length) {
|
|
1000
1060
|
skipWs();
|
|
1001
|
-
if (pos >= str.length)
|
|
1061
|
+
if (pos >= str.length)
|
|
1062
|
+
break;
|
|
1002
1063
|
if (str[pos] === ")") {
|
|
1003
1064
|
pos++;
|
|
1004
1065
|
return items;
|
|
1005
1066
|
}
|
|
1006
1067
|
const left = parseValue();
|
|
1007
|
-
if (left === void 0)
|
|
1068
|
+
if (left === void 0)
|
|
1069
|
+
break;
|
|
1008
1070
|
skipWs();
|
|
1009
1071
|
if (str[pos] === "." && (pos + 1 >= str.length || /\s/.test(str[pos + 1]) || str[pos + 1] === ")")) {
|
|
1010
1072
|
pos++;
|
|
@@ -1025,7 +1087,8 @@ function parseLispRecursive(str) {
|
|
|
1025
1087
|
return parseValue();
|
|
1026
1088
|
}
|
|
1027
1089
|
function lispPairsToObject(pairs) {
|
|
1028
|
-
if (!Array.isArray(pairs))
|
|
1090
|
+
if (!Array.isArray(pairs))
|
|
1091
|
+
return pairs;
|
|
1029
1092
|
const obj = {};
|
|
1030
1093
|
for (let i = 0; i < pairs.length - 1; i += 2) {
|
|
1031
1094
|
const key = pairs[i];
|
|
@@ -1036,36 +1099,18 @@ function lispPairsToObject(pairs) {
|
|
|
1036
1099
|
}
|
|
1037
1100
|
return obj;
|
|
1038
1101
|
}
|
|
1039
|
-
var ENTITY_SCHEMAS = {
|
|
1040
|
-
LINE: { fields: ["x1", "y1", "z1", "x2", "y2", "z2", "length"], strings: [] },
|
|
1041
|
-
CIRCLE: { fields: ["cx", "cy", "cz", "radius"], strings: [] },
|
|
1042
|
-
ARC: { fields: ["cx", "cy", "cz", "radius", "startAngle", "endAngle"], strings: [] },
|
|
1043
|
-
LWPOLYLINE: { fields: ["vertices", "closed"], strings: [] },
|
|
1044
|
-
TEXT: { fields: ["x", "y", "z", "text", "height", "rotation"], strings: ["text"] },
|
|
1045
|
-
MTEXT: { fields: ["x", "y", "z", "text", "height", "rotation"], strings: ["text"] },
|
|
1046
|
-
ATTRIB: { fields: ["x", "y", "z", "text", "height", "rotation"], strings: ["text"] },
|
|
1047
|
-
TCH_TEXT: { fields: ["x", "y", "z", "text", "height", "rotation"], strings: ["text"] },
|
|
1048
|
-
INSERT: { fields: ["x", "y", "z", "blockName", "rotation", "scaleX", "scaleY"], strings: ["blockName"] },
|
|
1049
|
-
POINT: { fields: ["x", "y", "z"], strings: [] }
|
|
1050
|
-
};
|
|
1051
1102
|
function parseEntity(arr) {
|
|
1052
|
-
if (!Array.isArray(arr) || arr.length < 5)
|
|
1053
|
-
|
|
1054
|
-
const
|
|
1055
|
-
|
|
1056
|
-
schema.fields.forEach((name, i) => {
|
|
1057
|
-
if (i < rest.length) {
|
|
1058
|
-
let val = rest[i];
|
|
1059
|
-
if (schema.strings.includes(name) && val !== null && val !== void 0) val = String(val);
|
|
1060
|
-
props[name] = val;
|
|
1061
|
-
}
|
|
1062
|
-
});
|
|
1063
|
-
return { type: String(type), handle: String(handle), layer: String(layer), color, linetype: String(linetype), ...props };
|
|
1103
|
+
if (!Array.isArray(arr) || arr.length < 5)
|
|
1104
|
+
return null;
|
|
1105
|
+
const [type, handle, layer, color, linetype] = arr;
|
|
1106
|
+
return { type: String(type), handle: String(handle), layer: String(layer), color, linetype: String(linetype) };
|
|
1064
1107
|
}
|
|
1065
|
-
function buildEntityCode({ type, layer, bbox
|
|
1108
|
+
function buildEntityCode({ type, layer, bbox }) {
|
|
1066
1109
|
const items = [];
|
|
1067
|
-
if (type)
|
|
1068
|
-
|
|
1110
|
+
if (type)
|
|
1111
|
+
items.push(`(cons 0 "${type.replace(/"/g, '\\"')}")`);
|
|
1112
|
+
if (layer)
|
|
1113
|
+
items.push(`(cons 8 "${layer.replace(/"/g, '\\"')}")`);
|
|
1069
1114
|
if (bbox) {
|
|
1070
1115
|
const parts = bbox.split(",").map((s) => parseFloat(s.trim()));
|
|
1071
1116
|
if (parts.length === 4) {
|
|
@@ -1081,55 +1126,22 @@ function buildEntityCode({ type, layer, bbox, offset, limit }) {
|
|
|
1081
1126
|
const filterExpr = items.length ? `(list ${items.join(" ")})` : "nil";
|
|
1082
1127
|
const ssgetExpr = items.length ? `(ssget "_X" ${filterExpr})` : '(ssget "_X")';
|
|
1083
1128
|
return `(progn
|
|
1084
|
-
(
|
|
1085
|
-
|
|
1086
|
-
(setq
|
|
1087
|
-
|
|
1088
|
-
(
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
(append result (list (car c) (cadr c) (caddr c) (cdr (assoc 40 ed)))))
|
|
1096
|
-
((= typ "ARC")
|
|
1097
|
-
(setq c (cdr (assoc 10 ed)))
|
|
1098
|
-
(append result (list (car c) (cadr c) (caddr c) (cdr (assoc 40 ed)) (cdr (assoc 50 ed)) (cdr (assoc 51 ed)))))
|
|
1099
|
-
((= typ "LWPOLYLINE")
|
|
1100
|
-
(setq verts nil closed nil)
|
|
1101
|
-
(foreach g ed
|
|
1102
|
-
(if (= (car g) 10) (setq verts (append verts (list (list (cadr g) (caddr g))))))
|
|
1103
|
-
(if (= (car g) 70) (setq closed (= (logand (cdr g) 1) 1))))
|
|
1104
|
-
(append result (list verts (if closed "T" nil))))
|
|
1105
|
-
((= typ "TEXT")
|
|
1106
|
-
(setq ins (cdr (assoc 10 ed)))
|
|
1107
|
-
(append result (list (car ins) (cadr ins) (caddr ins) (vl-prin1-to-string (cdr (assoc 1 ed))) (cdr (assoc 40 ed)) (cdr (assoc 50 ed))))))
|
|
1108
|
-
((= typ "MTEXT")
|
|
1109
|
-
(setq ins (cdr (assoc 10 ed)))
|
|
1110
|
-
(append result (list (car ins) (cadr ins) (caddr ins) (vl-prin1-to-string (cdr (assoc 1 ed))) (cdr (assoc 40 ed)) (cdr (assoc 50 ed))))))
|
|
1111
|
-
((= typ "INSERT")
|
|
1112
|
-
(setq ins (cdr (assoc 10 ed)))
|
|
1113
|
-
(append result (list (car ins) (cadr ins) (caddr ins) (vl-prin1-to-string (cdr (assoc 2 ed))) (cdr (assoc 50 ed)) (cdr (assoc 41 ed)) (cdr (assoc 42 ed))))))
|
|
1114
|
-
((= typ "POINT")
|
|
1115
|
-
(setq p (cdr (assoc 10 ed)))
|
|
1116
|
-
(append result (list (car p) (cadr p) (caddr p))))
|
|
1117
|
-
(t result)))
|
|
1118
|
-
(defun @e:run nil
|
|
1119
|
-
(setq ss ${ssgetExpr})
|
|
1120
|
-
(if (null ss)
|
|
1121
|
-
(list "total" 0 "offset" ${offset} "limit" ${limit})
|
|
1122
|
-
(progn
|
|
1123
|
-
(setq total (sslength ss) entities nil i ${offset})
|
|
1124
|
-
(while (and (< i total) (< (length entities) ${limit}))
|
|
1125
|
-
(setq entities (append entities (list (@e:props (ssname ss i)))) i (1+ i)))
|
|
1126
|
-
(list "total" total "offset" ${offset} "limit" ${limit} "entities" entities))))
|
|
1127
|
-
(@e:run))
|
|
1128
|
-
`;
|
|
1129
|
+
(vl-load-com)
|
|
1130
|
+
(defun @e:dp (ent / ed typ gc is)
|
|
1131
|
+
(setq ed (entget ent) typ (cdr (assoc 0 ed)) gc (assoc 62 ed) is (assoc 6 ed))
|
|
1132
|
+
(list typ (cdr (assoc 5 ed)) (cdr (assoc 8 ed))
|
|
1133
|
+
(if gc (cdr gc) 256)
|
|
1134
|
+
(if is (cdr is) "ByLayer")))
|
|
1135
|
+
(setq @e:total (if (setq @e:ss ${ssgetExpr}) (sslength @e:ss) 0)
|
|
1136
|
+
@e:ents nil @e:i 0)
|
|
1137
|
+
(while (and @e:ss (< @e:i @e:total)(< (length @e:ents) 100))
|
|
1138
|
+
(setq @e:ents (cons (@e:dp (ssname @e:ss @e:i)) @e:ents) @e:i (1+ @e:i)))
|
|
1139
|
+
(vl-prin1-to-string (list @e:total (reverse @e:ents))))`;
|
|
1129
1140
|
}
|
|
1130
1141
|
function buildTextCode({ layer, bbox, offset, limit }) {
|
|
1131
1142
|
const items = [`'(0 . "TEXT,MTEXT,ATTRIB,TCH_TEXT")`];
|
|
1132
|
-
if (layer)
|
|
1143
|
+
if (layer)
|
|
1144
|
+
items.push(`(cons 8 "${layer.replace(/"/g, '\\"')}")`);
|
|
1133
1145
|
if (bbox) {
|
|
1134
1146
|
const parts = bbox.split(",").map((s) => parseFloat(s.trim()));
|
|
1135
1147
|
if (parts.length === 4) {
|
|
@@ -1168,8 +1180,8 @@ function buildTextCode({ layer, bbox, offset, limit }) {
|
|
|
1168
1180
|
var RESOURCES = [
|
|
1169
1181
|
{ uri: "atlisp://cad/info", name: "CAD Info", description: "CAD \u8FDE\u63A5\u4FE1\u606F", mimeType: "application/json", subscribable: true },
|
|
1170
1182
|
{ uri: "atlisp://dwg/layers", name: "Layers", description: "\u56FE\u5C42\u5217\u8868", mimeType: "application/json", subscribable: true },
|
|
1171
|
-
{ uri: "atlisp://dwg/entities", name: "Entities", description: "\
|
|
1172
|
-
{ uri: "atlisp://dwg/texts", name: "Texts", description: "\u6587\u672C\u5B9E\u4F53\u5185\u5BB9\u5217\u8868 (TEXT/MTEXT/ATTRIB/TCH_TEXT)\uFF0C\u652F\u6301 ?layer=0&bbox=0,0,100,100&limit=
|
|
1183
|
+
{ uri: "atlisp://dwg/entities", name: "Entities", description: "\u56FE\u5143\u5217\u8868\uFF0C\u8FD4\u56DE\u603B\u6570\u548C\u524D100\u4E2A\u56FE\u5143\uFF08\u7C7B\u578B\u3001\u53E5\u67C4\u3001\u56FE\u5C42\u3001\u989C\u8272\u3001\u7EBF\u578B\uFF09\uFF0C\u652F\u6301 ?type=LINE&layer=0&bbox=0,0,100,100 \u8FC7\u6EE4", mimeType: "application/json", subscribable: true },
|
|
1184
|
+
{ uri: "atlisp://dwg/texts", name: "Texts", description: "\u6587\u672C\u5B9E\u4F53\u5185\u5BB9\u5217\u8868 (TEXT/MTEXT/ATTRIB/TCH_TEXT)\uFF0C\u652F\u6301 ?layer=0&bbox=0,0,100,100&limit=5000&offset=0", mimeType: "application/json", subscribable: true },
|
|
1173
1185
|
{ uri: "atlisp://dwg/name", name: "DWG Name", description: "\u5F53\u524D DWG \u6587\u4EF6\u540D", mimeType: "application/json", subscribable: true },
|
|
1174
1186
|
{ uri: "atlisp://dwg/path", name: "DWG Path", description: "\u6587\u4EF6\u5B8C\u6574\u8DEF\u5F84", mimeType: "application/json", subscribable: true },
|
|
1175
1187
|
{ uri: "atlisp://cad/dwgs", name: "DWG List", description: "\u6240\u6709\u6253\u5F00\u7684 DWG \u6587\u4EF6\u5217\u8868", mimeType: "application/json", subscribable: true },
|
|
@@ -1180,14 +1192,16 @@ var RESOURCES = [
|
|
|
1180
1192
|
];
|
|
1181
1193
|
function parseQuery(uri) {
|
|
1182
1194
|
const qIdx = uri.indexOf("?");
|
|
1183
|
-
if (qIdx === -1)
|
|
1195
|
+
if (qIdx === -1)
|
|
1196
|
+
return { base: uri, params: {} };
|
|
1184
1197
|
const base = uri.substring(0, qIdx);
|
|
1185
1198
|
const params = {};
|
|
1186
1199
|
uri.substring(qIdx + 1).split("&").forEach((p) => {
|
|
1187
1200
|
const eqIdx = p.indexOf("=");
|
|
1188
1201
|
const k = eqIdx === -1 ? p : p.substring(0, eqIdx);
|
|
1189
1202
|
const v = eqIdx === -1 ? "" : p.substring(eqIdx + 1);
|
|
1190
|
-
if (k)
|
|
1203
|
+
if (k)
|
|
1204
|
+
params[k] = decodeURIComponent(v);
|
|
1191
1205
|
});
|
|
1192
1206
|
return { base, params };
|
|
1193
1207
|
}
|
|
@@ -1231,7 +1245,8 @@ async function readResource(uri) {
|
|
|
1231
1245
|
}
|
|
1232
1246
|
async function getCadInfo2() {
|
|
1233
1247
|
const cached = getCached("cad:info");
|
|
1234
|
-
if (cached)
|
|
1248
|
+
if (cached)
|
|
1249
|
+
return cached;
|
|
1235
1250
|
if (!cad.connected) {
|
|
1236
1251
|
await cad.connect();
|
|
1237
1252
|
}
|
|
@@ -1258,11 +1273,14 @@ async function getCadInfo2() {
|
|
|
1258
1273
|
async function getLayers(filterName = null) {
|
|
1259
1274
|
const cacheKey = filterName ? `dwg:layers:${filterName}` : "dwg:layers:all";
|
|
1260
1275
|
const cached = getCached(cacheKey);
|
|
1261
|
-
if (cached)
|
|
1262
|
-
|
|
1263
|
-
if (!cad.connected)
|
|
1276
|
+
if (cached)
|
|
1277
|
+
return cached;
|
|
1278
|
+
if (!cad.connected)
|
|
1279
|
+
await cad.connect();
|
|
1280
|
+
if (!cad.connected)
|
|
1281
|
+
return [];
|
|
1264
1282
|
try {
|
|
1265
|
-
const code = filterName ? `(tblnext "LAYER" T)` : `(progn (setq res nil)(while (setq e (tblnext "LAYER" (null res)))(setq res (cons (list (cdr (assoc 2 e)) (cdr (assoc 62 e)) (cdr (assoc 70 e))) res))) (reverse res))`;
|
|
1283
|
+
const code = filterName ? `(vl-prin1-to-string (cdr (assoc 2 (tblnext "LAYER" T))))` : `(progn (setq res nil)(while (setq e (tblnext "LAYER" (null res)))(setq res (cons (list (vl-prin1-to-string (cdr (assoc 2 e))) (cdr (assoc 62 e)) (cdr (assoc 70 e))) res))) (reverse res))`;
|
|
1266
1284
|
const result = await cad.sendCommandWithResult(code);
|
|
1267
1285
|
if (!result || result === "" || result === "nil") {
|
|
1268
1286
|
setCache(cacheKey, []);
|
|
@@ -1307,46 +1325,42 @@ async function getLayers(filterName = null) {
|
|
|
1307
1325
|
async function getEntities(params = {}) {
|
|
1308
1326
|
const cacheKey = `dwg:entities:${JSON.stringify(params)}`;
|
|
1309
1327
|
const cached = getCached(cacheKey);
|
|
1310
|
-
if (cached)
|
|
1311
|
-
|
|
1328
|
+
if (cached)
|
|
1329
|
+
return cached;
|
|
1330
|
+
if (!cad.connected)
|
|
1331
|
+
await cad.connect();
|
|
1312
1332
|
if (!cad.connected) {
|
|
1313
1333
|
const result = { total: 0, entities: [] };
|
|
1314
1334
|
setCache(cacheKey, result);
|
|
1315
1335
|
return result;
|
|
1316
1336
|
}
|
|
1317
|
-
const offset = Math.max(0, parseInt(params.offset) || 0);
|
|
1318
|
-
const limit = Math.min(Math.max(1, parseInt(params.limit) || 100), 1e3);
|
|
1319
1337
|
try {
|
|
1320
1338
|
const code = buildEntityCode({
|
|
1321
1339
|
type: params.type || null,
|
|
1322
1340
|
layer: params.layer || null,
|
|
1323
|
-
bbox: params.bbox || null
|
|
1324
|
-
offset,
|
|
1325
|
-
limit
|
|
1341
|
+
bbox: params.bbox || null
|
|
1326
1342
|
});
|
|
1327
1343
|
const resultStr = await cad.sendCommandWithResult(code);
|
|
1328
|
-
if (!resultStr || resultStr === "" || resultStr === "nil"
|
|
1329
|
-
const
|
|
1330
|
-
setCache(cacheKey,
|
|
1331
|
-
return
|
|
1344
|
+
if (!resultStr || resultStr === "" || resultStr === "nil") {
|
|
1345
|
+
const result2 = { total: 0, entities: [] };
|
|
1346
|
+
setCache(cacheKey, result2);
|
|
1347
|
+
return result2;
|
|
1332
1348
|
}
|
|
1349
|
+
let total = 0;
|
|
1350
|
+
let entities = [];
|
|
1333
1351
|
const parsed = parseLispRecursive(resultStr);
|
|
1334
|
-
if (
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1352
|
+
if (parsed && Array.isArray(parsed) && parsed.length >= 2) {
|
|
1353
|
+
total = typeof parsed[0] === "number" ? parsed[0] : 0;
|
|
1354
|
+
const rawEntities = Array.isArray(parsed[1]) ? parsed[1] : [];
|
|
1355
|
+
entities = rawEntities.map(parseEntity).filter(Boolean);
|
|
1338
1356
|
}
|
|
1339
|
-
const
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
data.offset = offset;
|
|
1344
|
-
data.limit = limit;
|
|
1345
|
-
setCache(cacheKey, data);
|
|
1346
|
-
return data;
|
|
1357
|
+
const result = { total, entities };
|
|
1358
|
+
log(`getEntities: total=${total}, returned=${entities.length}`);
|
|
1359
|
+
setCache(cacheKey, result);
|
|
1360
|
+
return result;
|
|
1347
1361
|
} catch (e) {
|
|
1348
1362
|
log(`getEntities error: ${e.message}`);
|
|
1349
|
-
const result = { total: 0,
|
|
1363
|
+
const result = { total: 0, entities: [] };
|
|
1350
1364
|
setCache(cacheKey, result);
|
|
1351
1365
|
return result;
|
|
1352
1366
|
}
|
|
@@ -1354,15 +1368,17 @@ async function getEntities(params = {}) {
|
|
|
1354
1368
|
async function getTexts(params = {}) {
|
|
1355
1369
|
const cacheKey = `dwg:texts:${JSON.stringify(params)}`;
|
|
1356
1370
|
const cached = getCached(cacheKey);
|
|
1357
|
-
if (cached)
|
|
1358
|
-
|
|
1371
|
+
if (cached)
|
|
1372
|
+
return cached;
|
|
1373
|
+
if (!cad.connected)
|
|
1374
|
+
await cad.connect();
|
|
1359
1375
|
if (!cad.connected) {
|
|
1360
1376
|
const result = { total: 0, texts: [] };
|
|
1361
1377
|
setCache(cacheKey, result);
|
|
1362
1378
|
return result;
|
|
1363
1379
|
}
|
|
1364
1380
|
const offset = Math.max(0, parseInt(params.offset) || 0);
|
|
1365
|
-
const limit = Math.min(Math.max(1, parseInt(params.limit) ||
|
|
1381
|
+
const limit = Math.min(Math.max(1, parseInt(params.limit) || 5e3), 5e3);
|
|
1366
1382
|
try {
|
|
1367
1383
|
const code = buildTextCode({
|
|
1368
1384
|
layer: params.layer || null,
|
|
@@ -1393,8 +1409,10 @@ async function getTexts(params = {}) {
|
|
|
1393
1409
|
}
|
|
1394
1410
|
}
|
|
1395
1411
|
async function getDwgName() {
|
|
1396
|
-
if (!cad.connected)
|
|
1397
|
-
|
|
1412
|
+
if (!cad.connected)
|
|
1413
|
+
await cad.connect();
|
|
1414
|
+
if (!cad.connected)
|
|
1415
|
+
return { name: null };
|
|
1398
1416
|
try {
|
|
1399
1417
|
const code = `(vl-princ-to-string (getvar "dwgname"))`;
|
|
1400
1418
|
const name = await cad.sendCommandWithResult(code);
|
|
@@ -1404,8 +1422,10 @@ async function getDwgName() {
|
|
|
1404
1422
|
}
|
|
1405
1423
|
}
|
|
1406
1424
|
async function getDwgPath() {
|
|
1407
|
-
if (!cad.connected)
|
|
1408
|
-
|
|
1425
|
+
if (!cad.connected)
|
|
1426
|
+
await cad.connect();
|
|
1427
|
+
if (!cad.connected)
|
|
1428
|
+
return { path: null, name: null };
|
|
1409
1429
|
try {
|
|
1410
1430
|
const code = `(progn
|
|
1411
1431
|
(setq prefix (vl-princ-to-string (getvar "dwgprefix")))
|
|
@@ -1423,7 +1443,8 @@ async function getDwgPath() {
|
|
|
1423
1443
|
}
|
|
1424
1444
|
if (!parsed) {
|
|
1425
1445
|
const listResult = parseLispList(result);
|
|
1426
|
-
if (listResult && listResult.length >= 2)
|
|
1446
|
+
if (listResult && listResult.length >= 2)
|
|
1447
|
+
parsed = listResult;
|
|
1427
1448
|
}
|
|
1428
1449
|
if (parsed && Array.isArray(parsed) && parsed.length >= 2) {
|
|
1429
1450
|
return { path: String(parsed[0]), name: String(parsed[1]) };
|
|
@@ -1436,9 +1457,12 @@ async function getDwgPath() {
|
|
|
1436
1457
|
async function getPackages(filterName = null) {
|
|
1437
1458
|
const cacheKey = filterName ? `packages:${filterName}` : "packages:all";
|
|
1438
1459
|
const cached = getCached(cacheKey);
|
|
1439
|
-
if (cached)
|
|
1440
|
-
|
|
1441
|
-
if (!cad.connected)
|
|
1460
|
+
if (cached)
|
|
1461
|
+
return cached;
|
|
1462
|
+
if (!cad.connected)
|
|
1463
|
+
await cad.connect();
|
|
1464
|
+
if (!cad.connected)
|
|
1465
|
+
return [];
|
|
1442
1466
|
try {
|
|
1443
1467
|
const code = `(mapcar 'cdr @::*local-pkgs*)`;
|
|
1444
1468
|
const result = await cad.sendCommandWithResult(code);
|
|
@@ -1452,7 +1476,8 @@ async function getPackages(filterName = null) {
|
|
|
1452
1476
|
} catch {
|
|
1453
1477
|
raw = parseLispList(result) || [];
|
|
1454
1478
|
}
|
|
1455
|
-
if (!Array.isArray(raw))
|
|
1479
|
+
if (!Array.isArray(raw))
|
|
1480
|
+
raw = [];
|
|
1456
1481
|
const packages = raw.map((item) => {
|
|
1457
1482
|
if (Array.isArray(item)) {
|
|
1458
1483
|
const pkg = { name: "", version: "0.0.0", description: "", loaded: true };
|
|
@@ -1461,13 +1486,20 @@ async function getPackages(filterName = null) {
|
|
|
1461
1486
|
const [[key, val]] = Object.entries(entry);
|
|
1462
1487
|
const k = String(key);
|
|
1463
1488
|
const v = String(val);
|
|
1464
|
-
if (k === ":NAME")
|
|
1465
|
-
|
|
1466
|
-
else if (k === ":
|
|
1467
|
-
|
|
1468
|
-
else if (k === ":
|
|
1469
|
-
|
|
1470
|
-
else if (k === ":
|
|
1489
|
+
if (k === ":NAME")
|
|
1490
|
+
pkg.name = v;
|
|
1491
|
+
else if (k === ":VERSION")
|
|
1492
|
+
pkg.version = v;
|
|
1493
|
+
else if (k === ":DESCRIPTION")
|
|
1494
|
+
pkg.description = v;
|
|
1495
|
+
else if (k === ":FULL-NAME")
|
|
1496
|
+
pkg.fullName = v;
|
|
1497
|
+
else if (k === ":AUTHOR")
|
|
1498
|
+
pkg.author = v;
|
|
1499
|
+
else if (k === ":CATEGORY")
|
|
1500
|
+
pkg.category = v;
|
|
1501
|
+
else if (k === ":URL")
|
|
1502
|
+
pkg.url = v;
|
|
1471
1503
|
}
|
|
1472
1504
|
}
|
|
1473
1505
|
return pkg;
|
|
@@ -1478,15 +1510,22 @@ async function getPackages(filterName = null) {
|
|
|
1478
1510
|
if (item && typeof item === "object") {
|
|
1479
1511
|
const pkg = { name: "", version: "0.0.0", description: "", loaded: true };
|
|
1480
1512
|
const nameVal = item.name || item.Name || item.NAME || item[":NAME"];
|
|
1481
|
-
if (nameVal)
|
|
1513
|
+
if (nameVal)
|
|
1514
|
+
pkg.name = String(nameVal);
|
|
1482
1515
|
const verVal = item.version || item.Version || item.VERSION || item[":VERSION"];
|
|
1483
|
-
if (verVal)
|
|
1516
|
+
if (verVal)
|
|
1517
|
+
pkg.version = String(verVal);
|
|
1484
1518
|
const descVal = item.description || item.Description || item.DESCRIPTION || item[":DESCRIPTION"];
|
|
1485
|
-
if (descVal)
|
|
1486
|
-
|
|
1487
|
-
if (item.
|
|
1488
|
-
|
|
1489
|
-
if (item.
|
|
1519
|
+
if (descVal)
|
|
1520
|
+
pkg.description = String(descVal);
|
|
1521
|
+
if (item.fullName || item.full_name)
|
|
1522
|
+
pkg.fullName = String(item.fullName || item.full_name);
|
|
1523
|
+
if (item.author || item.Author)
|
|
1524
|
+
pkg.author = String(item.author || item.Author);
|
|
1525
|
+
if (item.category || item.Category)
|
|
1526
|
+
pkg.category = String(item.category || item.Category);
|
|
1527
|
+
if (item.url || item.Url || item.URL)
|
|
1528
|
+
pkg.url = String(item.url || item.Url || item.URL);
|
|
1490
1529
|
return pkg;
|
|
1491
1530
|
}
|
|
1492
1531
|
return null;
|
|
@@ -1512,9 +1551,12 @@ function getPlatforms() {
|
|
|
1512
1551
|
async function getDwgList() {
|
|
1513
1552
|
const cacheKey = "cad:dwgs";
|
|
1514
1553
|
const cached = getCached(cacheKey);
|
|
1515
|
-
if (cached)
|
|
1516
|
-
|
|
1517
|
-
if (!cad.connected)
|
|
1554
|
+
if (cached)
|
|
1555
|
+
return cached;
|
|
1556
|
+
if (!cad.connected)
|
|
1557
|
+
await cad.connect();
|
|
1558
|
+
if (!cad.connected)
|
|
1559
|
+
return [];
|
|
1518
1560
|
try {
|
|
1519
1561
|
const code = `(progn
|
|
1520
1562
|
(vl-load-com)
|
|
@@ -1538,7 +1580,8 @@ async function getDwgList() {
|
|
|
1538
1580
|
parsed = listResult;
|
|
1539
1581
|
}
|
|
1540
1582
|
}
|
|
1541
|
-
if (!Array.isArray(parsed))
|
|
1583
|
+
if (!Array.isArray(parsed))
|
|
1584
|
+
parsed = [];
|
|
1542
1585
|
const dwgList = parsed.map((item) => {
|
|
1543
1586
|
if (Array.isArray(item) && item.length >= 2) {
|
|
1544
1587
|
return { name: String(item[0]), path: String(item[1]) };
|
|
@@ -1565,7 +1608,8 @@ function loadStandardsFile(filename) {
|
|
|
1565
1608
|
var standardsCache = /* @__PURE__ */ new Map();
|
|
1566
1609
|
function getCachedStandards(key) {
|
|
1567
1610
|
const entry = standardsCache.get(key);
|
|
1568
|
-
if (entry && Date.now() - entry.timestamp < 3e4)
|
|
1611
|
+
if (entry && Date.now() - entry.timestamp < 3e4)
|
|
1612
|
+
return entry.data;
|
|
1569
1613
|
standardsCache.delete(key);
|
|
1570
1614
|
return null;
|
|
1571
1615
|
}
|
|
@@ -1574,16 +1618,20 @@ function setCachedStandards(key, data) {
|
|
|
1574
1618
|
}
|
|
1575
1619
|
function getDraftingStandards() {
|
|
1576
1620
|
const cached = getCachedStandards("drafting");
|
|
1577
|
-
if (cached)
|
|
1621
|
+
if (cached)
|
|
1622
|
+
return cached;
|
|
1578
1623
|
const data = loadStandardsFile("drafting.json");
|
|
1579
|
-
if (data)
|
|
1624
|
+
if (data)
|
|
1625
|
+
setCachedStandards("drafting", data);
|
|
1580
1626
|
return data || { error: "\u5236\u56FE\u89C4\u8303\u6587\u4EF6\u52A0\u8F7D\u5931\u8D25" };
|
|
1581
1627
|
}
|
|
1582
1628
|
function getCodingStandards() {
|
|
1583
1629
|
const cached = getCachedStandards("coding");
|
|
1584
|
-
if (cached)
|
|
1630
|
+
if (cached)
|
|
1631
|
+
return cached;
|
|
1585
1632
|
const data = loadStandardsFile("coding.json");
|
|
1586
|
-
if (data)
|
|
1633
|
+
if (data)
|
|
1634
|
+
setCachedStandards("coding", data);
|
|
1587
1635
|
return data || { error: "\u7F16\u7801\u89C4\u8303\u6587\u4EF6\u52A0\u8F7D\u5931\u8D25" };
|
|
1588
1636
|
}
|
|
1589
1637
|
|
|
@@ -1837,10 +1885,14 @@ ${generateSuggestions(entities, layers)}`
|
|
|
1837
1885
|
}
|
|
1838
1886
|
function generateSuggestions(entities, layers) {
|
|
1839
1887
|
const suggestions = [];
|
|
1840
|
-
if (entities.total > 1e3)
|
|
1841
|
-
|
|
1842
|
-
if (
|
|
1843
|
-
|
|
1888
|
+
if (entities.total > 1e3)
|
|
1889
|
+
suggestions.push("- \u56FE\u7EB8\u5B9E\u4F53\u8F83\u591A\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u56FE\u5C42\u5206\u7C7B\u7BA1\u7406");
|
|
1890
|
+
if (layers.length > 20)
|
|
1891
|
+
suggestions.push("- \u56FE\u5C42\u8F83\u591A\uFF0C\u5EFA\u8BAE\u6E05\u7406\u672A\u4F7F\u7528\u7684\u56FE\u5C42");
|
|
1892
|
+
if (entities.byType.LINE && entities.byType.LINE > 500)
|
|
1893
|
+
suggestions.push("- \u7EBF\u6761\u8F83\u591A\uFF0C\u53EF\u8003\u8651\u4F7F\u7528 BLOCK \u51CF\u5C11\u5B9E\u4F53\u6570\u91CF");
|
|
1894
|
+
if (!entities.byType.DIMENSION)
|
|
1895
|
+
suggestions.push("- \u672A\u53D1\u73B0\u5C3A\u5BF8\u6807\u6CE8\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u6807\u6CE8");
|
|
1844
1896
|
return suggestions.length ? suggestions.join("\n") : "- \u56FE\u7EB8\u7ED3\u6784\u826F\u597D";
|
|
1845
1897
|
}
|
|
1846
1898
|
async function generateBatchLinesPrompt(args) {
|
|
@@ -2568,9 +2620,11 @@ var SseSession = class {
|
|
|
2568
2620
|
return lines.join("\n") + "\n\n";
|
|
2569
2621
|
}
|
|
2570
2622
|
_setupDrain() {
|
|
2571
|
-
if (typeof this.#res.on !== "function")
|
|
2623
|
+
if (typeof this.#res.on !== "function")
|
|
2624
|
+
return;
|
|
2572
2625
|
this.#drainHandler = () => {
|
|
2573
|
-
if (!this.#active)
|
|
2626
|
+
if (!this.#active)
|
|
2627
|
+
return;
|
|
2574
2628
|
if (this.#backpressureBuffer.length > 0) {
|
|
2575
2629
|
this._drainBuffer();
|
|
2576
2630
|
}
|
|
@@ -2592,7 +2646,8 @@ var SseSession = class {
|
|
|
2592
2646
|
}
|
|
2593
2647
|
}
|
|
2594
2648
|
_write(content) {
|
|
2595
|
-
if (!this.#active)
|
|
2649
|
+
if (!this.#active)
|
|
2650
|
+
return false;
|
|
2596
2651
|
try {
|
|
2597
2652
|
if (this.#backpressureBuffer.length > 0) {
|
|
2598
2653
|
this.#backpressureBuffer.push(content);
|
|
@@ -2720,7 +2775,8 @@ function persistSessionData(clientId, sessionData) {
|
|
|
2720
2775
|
function loadPersistedSessionData(clientId) {
|
|
2721
2776
|
try {
|
|
2722
2777
|
const filePath = getSessionStorePath(clientId);
|
|
2723
|
-
if (!fs5.existsSync(filePath))
|
|
2778
|
+
if (!fs5.existsSync(filePath))
|
|
2779
|
+
return null;
|
|
2724
2780
|
const raw = fs5.readFileSync(filePath, "utf-8");
|
|
2725
2781
|
const store = JSON.parse(raw);
|
|
2726
2782
|
if (Date.now() - store.savedAt > SESSION_STORE_TTL) {
|
|
@@ -2909,7 +2965,8 @@ var SERVER_CAPABILITIES = {
|
|
|
2909
2965
|
prompts: {}
|
|
2910
2966
|
};
|
|
2911
2967
|
var { port, host, transport, apiKey, rateLimitWindow, rateLimitMax } = config_default;
|
|
2912
|
-
if (apiKey)
|
|
2968
|
+
if (apiKey)
|
|
2969
|
+
log("API Key authentication enabled");
|
|
2913
2970
|
var mcpLimiter = rateLimit({
|
|
2914
2971
|
windowMs: rateLimitWindow,
|
|
2915
2972
|
max: rateLimitMax,
|
|
@@ -2994,7 +3051,8 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
2994
3051
|
},
|
|
2995
3052
|
import_funlib: async (a) => {
|
|
2996
3053
|
const data = await loadAtlibFunctionLib();
|
|
2997
|
-
if (!data)
|
|
3054
|
+
if (!data)
|
|
3055
|
+
return { content: [{ type: "text", text: "\u52A0\u8F7D\u51FD\u6570\u5E93\u5931\u8D25" }], isError: true };
|
|
2998
3056
|
if (a.format === "list") {
|
|
2999
3057
|
const items = Object.values(data.all_functions || {}).map((f) => `${f.name}: ${f.description || ""}`);
|
|
3000
3058
|
return { content: [{ type: "text", text: items.join("\n") }] };
|
|
@@ -3183,7 +3241,8 @@ var tools = [
|
|
|
3183
3241
|
];
|
|
3184
3242
|
async function handleToolCall(name, args) {
|
|
3185
3243
|
const handler = TOOL_HANDLERS[name];
|
|
3186
|
-
if (!handler)
|
|
3244
|
+
if (!handler)
|
|
3245
|
+
return { content: [{ type: "text", text: `\u672A\u77E5\u5DE5\u5177: ${name}` }], isError: true };
|
|
3187
3246
|
try {
|
|
3188
3247
|
const result = await handler(args || {});
|
|
3189
3248
|
notifyResourceChanges(name);
|
|
@@ -3306,7 +3365,8 @@ async function startServer() {
|
|
|
3306
3365
|
const JSON_CONTENT_TYPES = ["application/json", "application/json-rpc", "application/vnd.api+json"];
|
|
3307
3366
|
app.use(async (req, res, next) => {
|
|
3308
3367
|
const ct = (req.headers["content-type"] || "").toLowerCase();
|
|
3309
|
-
if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
|
|
3368
|
+
if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
|
|
3369
|
+
return next();
|
|
3310
3370
|
try {
|
|
3311
3371
|
const buf = await rawBody(req, { limit: "10mb" });
|
|
3312
3372
|
const m = ct.match(/charset\s*=\s*([^\s;]+)/i);
|
|
@@ -3327,9 +3387,11 @@ async function startServer() {
|
|
|
3327
3387
|
const PUBLIC_PATHS = ["/health"];
|
|
3328
3388
|
if (apiKey) {
|
|
3329
3389
|
app.use((req, res, next) => {
|
|
3330
|
-
if (PUBLIC_PATHS.includes(req.path))
|
|
3390
|
+
if (PUBLIC_PATHS.includes(req.path))
|
|
3391
|
+
return next();
|
|
3331
3392
|
const auth = req.get("Authorization");
|
|
3332
|
-
if (auth === `Bearer ${apiKey}`)
|
|
3393
|
+
if (auth === `Bearer ${apiKey}`)
|
|
3394
|
+
return next();
|
|
3333
3395
|
res.status(401).json({ error: "Unauthorized" });
|
|
3334
3396
|
});
|
|
3335
3397
|
}
|
|
@@ -3344,7 +3406,8 @@ async function startServer() {
|
|
|
3344
3406
|
res.setHeader("Access-Control-Expose-Headers", "mcp-session-id, content-type, x-accel-buffering");
|
|
3345
3407
|
res.setHeader("Access-Control-Max-Age", "86400");
|
|
3346
3408
|
res.setHeader("Vary", "Accept");
|
|
3347
|
-
if (req.method === "OPTIONS")
|
|
3409
|
+
if (req.method === "OPTIONS")
|
|
3410
|
+
return res.status(204).end();
|
|
3348
3411
|
next();
|
|
3349
3412
|
});
|
|
3350
3413
|
}
|