@atlisp/mcp 1.3.2 → 1.3.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 +142 -76
- package/dist/cad-worker.js +43 -27
- package/package.json +1 -1
package/dist/atlisp-mcp.js
CHANGED
|
@@ -34,7 +34,8 @@ var SessionTransport = class {
|
|
|
34
34
|
this._started = true;
|
|
35
35
|
}
|
|
36
36
|
async send(message) {
|
|
37
|
-
if (this._closed)
|
|
37
|
+
if (this._closed)
|
|
38
|
+
return;
|
|
38
39
|
if (this._pendingRequest) {
|
|
39
40
|
const { resolve, reject, timeout } = this._pendingRequest;
|
|
40
41
|
clearTimeout(timeout);
|
|
@@ -43,7 +44,8 @@ var SessionTransport = class {
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
async close() {
|
|
46
|
-
if (this._closed)
|
|
47
|
+
if (this._closed)
|
|
48
|
+
return;
|
|
47
49
|
this._closed = true;
|
|
48
50
|
if (this._pendingRequest) {
|
|
49
51
|
const { reject, timeout } = this._pendingRequest;
|
|
@@ -210,7 +212,8 @@ function setupStdoutHandler(w) {
|
|
|
210
212
|
const lines = buffer.split("\n");
|
|
211
213
|
buffer = lines.pop() || "";
|
|
212
214
|
for (const line of lines) {
|
|
213
|
-
if (!line.trim())
|
|
215
|
+
if (!line.trim())
|
|
216
|
+
continue;
|
|
214
217
|
try {
|
|
215
218
|
const result = JSON.parse(line);
|
|
216
219
|
const rid = result.requestId;
|
|
@@ -235,7 +238,8 @@ function setupStdoutHandler(w) {
|
|
|
235
238
|
}
|
|
236
239
|
function getWorker() {
|
|
237
240
|
if (!worker || !worker.connected) {
|
|
238
|
-
if (worker)
|
|
241
|
+
if (worker)
|
|
242
|
+
worker.kill();
|
|
239
243
|
worker = spawn("node", [workerPath], {
|
|
240
244
|
stdio: ["pipe", "pipe", "pipe"]
|
|
241
245
|
});
|
|
@@ -244,7 +248,8 @@ function getWorker() {
|
|
|
244
248
|
const w = worker;
|
|
245
249
|
w.on("exit", (code) => {
|
|
246
250
|
console.error("worker exited:", code);
|
|
247
|
-
if (w !== worker)
|
|
251
|
+
if (w !== worker)
|
|
252
|
+
return;
|
|
248
253
|
w.connected = false;
|
|
249
254
|
for (const [id, { reject, timeout }] of pendingRequests) {
|
|
250
255
|
clearTimeout(timeout);
|
|
@@ -263,7 +268,8 @@ function getWorker() {
|
|
|
263
268
|
return worker;
|
|
264
269
|
}
|
|
265
270
|
function startHeartbeat() {
|
|
266
|
-
if (heartbeatTimer)
|
|
271
|
+
if (heartbeatTimer)
|
|
272
|
+
clearInterval(heartbeatTimer);
|
|
267
273
|
heartbeatTimer = setInterval(async () => {
|
|
268
274
|
try {
|
|
269
275
|
const result = await sendMessage({ type: "ping" });
|
|
@@ -308,7 +314,8 @@ var CadConnection = class {
|
|
|
308
314
|
return process.platform === "win32";
|
|
309
315
|
}
|
|
310
316
|
async connect() {
|
|
311
|
-
if (!this.isAvailable())
|
|
317
|
+
if (!this.isAvailable())
|
|
318
|
+
return false;
|
|
312
319
|
try {
|
|
313
320
|
const result = await sendMessage({ type: "connect" });
|
|
314
321
|
if (result && result.success) {
|
|
@@ -324,13 +331,16 @@ var CadConnection = class {
|
|
|
324
331
|
return false;
|
|
325
332
|
}
|
|
326
333
|
async sendCommand(code) {
|
|
327
|
-
if (!this.connected)
|
|
334
|
+
if (!this.connected)
|
|
335
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
328
336
|
const result = await sendMessage({ type: "send", code, platform: _platform });
|
|
329
|
-
if (result.success)
|
|
337
|
+
if (result.success)
|
|
338
|
+
return true;
|
|
330
339
|
throw new Error(result.error || "\u53D1\u9001\u5931\u8D25");
|
|
331
340
|
}
|
|
332
341
|
async sendCommandWithResult(code, encoding = null) {
|
|
333
|
-
if (!this.connected)
|
|
342
|
+
if (!this.connected)
|
|
343
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
334
344
|
const result = await sendMessage({ type: "sendResult", code, platform: _platform, encoding: encoding || "" });
|
|
335
345
|
if (result.success) {
|
|
336
346
|
return result.result || "";
|
|
@@ -344,7 +354,8 @@ var CadConnection = class {
|
|
|
344
354
|
return this.product;
|
|
345
355
|
}
|
|
346
356
|
async isBusy() {
|
|
347
|
-
if (!this.connected)
|
|
357
|
+
if (!this.connected)
|
|
358
|
+
return false;
|
|
348
359
|
try {
|
|
349
360
|
const result = await sendMessage({ type: "isBusy", platform: _platform });
|
|
350
361
|
return result && result.isBusy;
|
|
@@ -353,7 +364,8 @@ var CadConnection = class {
|
|
|
353
364
|
}
|
|
354
365
|
}
|
|
355
366
|
async hasDoc() {
|
|
356
|
-
if (!this.connected)
|
|
367
|
+
if (!this.connected)
|
|
368
|
+
return { hasDoc: false, docCount: 0 };
|
|
357
369
|
try {
|
|
358
370
|
const result = await sendMessage({ type: "hasdoc", platform: _platform });
|
|
359
371
|
return result || { hasDoc: false, docCount: 0 };
|
|
@@ -362,7 +374,8 @@ var CadConnection = class {
|
|
|
362
374
|
}
|
|
363
375
|
}
|
|
364
376
|
async newDoc() {
|
|
365
|
-
if (!this.connected)
|
|
377
|
+
if (!this.connected)
|
|
378
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
366
379
|
try {
|
|
367
380
|
const result = await sendMessage({ type: "newdoc", platform: _platform });
|
|
368
381
|
return result && result.success;
|
|
@@ -371,7 +384,8 @@ var CadConnection = class {
|
|
|
371
384
|
}
|
|
372
385
|
}
|
|
373
386
|
async bringToFront() {
|
|
374
|
-
if (!this.connected)
|
|
387
|
+
if (!this.connected)
|
|
388
|
+
throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
375
389
|
try {
|
|
376
390
|
const result = await sendMessage({ type: "bringToFront", platform: _platform });
|
|
377
391
|
return result && result.success;
|
|
@@ -380,7 +394,8 @@ var CadConnection = class {
|
|
|
380
394
|
}
|
|
381
395
|
}
|
|
382
396
|
async getInfo() {
|
|
383
|
-
if (!this.connected)
|
|
397
|
+
if (!this.connected)
|
|
398
|
+
return "CAD \u672A\u8FDE\u63A5";
|
|
384
399
|
return `Platform: ${this.product}, Version: ${this.version}, Status: Connected`;
|
|
385
400
|
}
|
|
386
401
|
async disconnect() {
|
|
@@ -462,7 +477,7 @@ async function evalLisp(code, withResult = false, encoding = null) {
|
|
|
462
477
|
}
|
|
463
478
|
return { content: [{ type: "text", text: "\u6267\u884C\u5931\u8D25\u6216\u65E0\u8FD4\u56DE\u503C" }], isError: true };
|
|
464
479
|
} else {
|
|
465
|
-
await cad.sendCommand(
|
|
480
|
+
await cad.sendCommand(code + "\n");
|
|
466
481
|
return { content: [{ type: "text", text: `\u5DF2\u53D1\u9001\u547D\u4EE4: ${code}` }] };
|
|
467
482
|
}
|
|
468
483
|
} catch (e) {
|
|
@@ -473,20 +488,23 @@ async function getCadInfo() {
|
|
|
473
488
|
if (!cad.connected) {
|
|
474
489
|
await cad.connect();
|
|
475
490
|
}
|
|
476
|
-
if (!cad.connected)
|
|
491
|
+
if (!cad.connected)
|
|
492
|
+
return { content: [{ type: "text", text: "CAD \u672A\u8FDE\u63A5" }] };
|
|
477
493
|
const info = await cad.getInfo();
|
|
478
494
|
return { content: [{ type: "text", text: info }] };
|
|
479
495
|
}
|
|
480
496
|
async function atCommand(command) {
|
|
481
|
-
if (!cad.connected)
|
|
482
|
-
|
|
497
|
+
if (!cad.connected)
|
|
498
|
+
return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
|
|
499
|
+
await cad.sendCommand(command + "\n");
|
|
483
500
|
return { content: [{ type: "text", text: `\u5DF2\u53D1\u9001\u547D\u4EE4: ${command}` }] };
|
|
484
501
|
}
|
|
485
502
|
async function newDocument() {
|
|
486
503
|
if (!cad.connected) {
|
|
487
504
|
await cad.connect();
|
|
488
505
|
}
|
|
489
|
-
if (!cad.connected)
|
|
506
|
+
if (!cad.connected)
|
|
507
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
490
508
|
const result = await cad.newDoc();
|
|
491
509
|
if (result) {
|
|
492
510
|
return { content: [{ type: "text", text: "\u5DF2\u5728 CAD \u4E2D\u65B0\u5EFA\u7A7A\u767D\u6587\u6863" }] };
|
|
@@ -497,7 +515,8 @@ async function bringToFront() {
|
|
|
497
515
|
if (!cad.connected) {
|
|
498
516
|
await cad.connect();
|
|
499
517
|
}
|
|
500
|
-
if (!cad.connected)
|
|
518
|
+
if (!cad.connected)
|
|
519
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
501
520
|
const result = await cad.bringToFront();
|
|
502
521
|
if (result) {
|
|
503
522
|
return { content: [{ type: "text", text: "\u5DF2\u5C06 CAD \u7A97\u53E3\u5207\u6362\u5230\u524D\u53F0" }] };
|
|
@@ -508,19 +527,22 @@ async function installAtlisp() {
|
|
|
508
527
|
if (!cad.connected) {
|
|
509
528
|
await cad.connect();
|
|
510
529
|
}
|
|
511
|
-
if (!cad.connected)
|
|
530
|
+
if (!cad.connected)
|
|
531
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
512
532
|
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))))`;
|
|
513
|
-
await cad.sendCommand(
|
|
533
|
+
await cad.sendCommand(installCode + "\n");
|
|
514
534
|
return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001 @lisp \u5B89\u88C5\u4EE3\u7801\u5230 CAD" }] };
|
|
515
535
|
}
|
|
516
536
|
async function listFunctionsInCad() {
|
|
517
537
|
if (!cad.connected) {
|
|
518
538
|
await cad.connect();
|
|
519
539
|
}
|
|
520
|
-
if (!cad.connected)
|
|
540
|
+
if (!cad.connected)
|
|
541
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
521
542
|
try {
|
|
522
543
|
const result = await cad.sendCommandWithResult("(atoms-family 0)", null);
|
|
523
|
-
if (result)
|
|
544
|
+
if (result)
|
|
545
|
+
return { content: [{ type: "text", text: result }] };
|
|
524
546
|
return { content: [{ type: "text", text: "CAD \u51FD\u6570\u5217\u8868\u4E3A\u7A7A" }] };
|
|
525
547
|
} catch (e) {
|
|
526
548
|
return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
|
|
@@ -530,7 +552,8 @@ async function initAtlisp() {
|
|
|
530
552
|
if (!cad.connected) {
|
|
531
553
|
await cad.connect();
|
|
532
554
|
}
|
|
533
|
-
if (!cad.connected)
|
|
555
|
+
if (!cad.connected)
|
|
556
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
534
557
|
const code = `(if (null @::load-module)
|
|
535
558
|
(progn
|
|
536
559
|
(vl-load-com)
|
|
@@ -540,7 +563,7 @@ async function initAtlisp() {
|
|
|
540
563
|
(v o'WaitforResponse 1000)
|
|
541
564
|
(e(r(vlax-get o'ResponseText)))))`;
|
|
542
565
|
try {
|
|
543
|
-
await cad.sendCommand(
|
|
566
|
+
await cad.sendCommand(code + "\n");
|
|
544
567
|
return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001 @lisp \u51FD\u6570\u5E93\u52A0\u8F7D\u4EE3\u7801\u5230 CAD" }] };
|
|
545
568
|
} catch (e) {
|
|
546
569
|
return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
|
|
@@ -570,10 +593,13 @@ async function fetchPackages() {
|
|
|
570
593
|
return null;
|
|
571
594
|
}
|
|
572
595
|
async function listPackages() {
|
|
573
|
-
if (!cad.connected)
|
|
574
|
-
|
|
596
|
+
if (!cad.connected)
|
|
597
|
+
await cad.connect();
|
|
598
|
+
if (!cad.connected)
|
|
599
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
575
600
|
const result = await cad.sendCommandWithResult("(@::package-list-in-local)");
|
|
576
|
-
if (result && result !== "nil")
|
|
601
|
+
if (result && result !== "nil")
|
|
602
|
+
return { content: [{ type: "text", text: result }] };
|
|
577
603
|
const packages = MOCK_PACKAGES.map((p) => `${p.name} v${p.version} - ${p.description}`);
|
|
578
604
|
return { content: [{ type: "text", text: `\u5DF2\u5B89\u88C5\u7684 @lisp \u5305:
|
|
579
605
|
${packages.join("\n")}` }] };
|
|
@@ -590,10 +616,12 @@ async function searchPackages(query) {
|
|
|
590
616
|
for (const p of items) {
|
|
591
617
|
const name = (p.name || "").toLowerCase();
|
|
592
618
|
const desc = (p.description || "").toLowerCase();
|
|
593
|
-
if (name.includes(q) || desc.includes(q))
|
|
619
|
+
if (name.includes(q) || desc.includes(q))
|
|
620
|
+
results.push(p);
|
|
594
621
|
}
|
|
595
622
|
} else {
|
|
596
|
-
for (const p of items)
|
|
623
|
+
for (const p of items)
|
|
624
|
+
results.push(p);
|
|
597
625
|
}
|
|
598
626
|
if (results.length === 0) {
|
|
599
627
|
return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5305\u542B "${query}" \u7684\u5305` }] };
|
|
@@ -633,9 +661,10 @@ async function getFunctionUsage(funcName, packageName) {
|
|
|
633
661
|
const response = await fetch(FUNCTIONS_URL, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
634
662
|
if (response.ok) {
|
|
635
663
|
const data = await response.json();
|
|
636
|
-
const funcs = data.
|
|
664
|
+
const funcs = Object.values(data.all_functions || {});
|
|
637
665
|
const func = funcs.find((f2) => f2.name === funcName || f2.name === `${packageName}:${funcName}`);
|
|
638
|
-
if (func)
|
|
666
|
+
if (func)
|
|
667
|
+
results.push(func);
|
|
639
668
|
}
|
|
640
669
|
} catch (e) {
|
|
641
670
|
log(`function-handlers fetch error: ${e.message}`);
|
|
@@ -646,7 +675,8 @@ async function getFunctionUsage(funcName, packageName) {
|
|
|
646
675
|
const raw = await fs2.readFile(path3.join(FUNCTIONS_DIR, file), "utf-8");
|
|
647
676
|
const data = JSON.parse(raw);
|
|
648
677
|
const func = data.functions?.find((f2) => f2.name === funcName);
|
|
649
|
-
if (func)
|
|
678
|
+
if (func)
|
|
679
|
+
results.push(func);
|
|
650
680
|
}
|
|
651
681
|
}
|
|
652
682
|
if (results.length === 0) {
|
|
@@ -663,14 +693,14 @@ async function getFunctionUsage(funcName, packageName) {
|
|
|
663
693
|
return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
|
|
664
694
|
}
|
|
665
695
|
}
|
|
666
|
-
async function
|
|
696
|
+
async function listSymbols(packageName) {
|
|
667
697
|
try {
|
|
668
698
|
let allFuncs = [];
|
|
669
699
|
try {
|
|
670
700
|
const response = await fetch(FUNCTIONS_URL, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
671
701
|
if (response.ok) {
|
|
672
702
|
const data = await response.json();
|
|
673
|
-
const funcs = data.
|
|
703
|
+
const funcs = Object.values(data.all_functions || {});
|
|
674
704
|
if (packageName) {
|
|
675
705
|
allFuncs = funcs.filter((f) => f.name.startsWith(`${packageName}:`));
|
|
676
706
|
} else {
|
|
@@ -686,7 +716,7 @@ async function listFunctions(packageName) {
|
|
|
686
716
|
try {
|
|
687
717
|
const raw = await fs2.readFile(path3.join(FUNCTIONS_DIR, file), "utf-8");
|
|
688
718
|
const data = JSON.parse(raw);
|
|
689
|
-
const funcs = data.
|
|
719
|
+
const funcs = Object.values(data.all_functions || {});
|
|
690
720
|
if (packageName) {
|
|
691
721
|
allFuncs = funcs.filter((f) => f.name.startsWith(`${packageName}:`));
|
|
692
722
|
} else {
|
|
@@ -727,11 +757,14 @@ function setCache(key, data) {
|
|
|
727
757
|
resourceCache.set(key, { data, timestamp: Date.now() });
|
|
728
758
|
}
|
|
729
759
|
function parseLispList(str) {
|
|
730
|
-
if (!str || typeof str !== "string")
|
|
760
|
+
if (!str || typeof str !== "string")
|
|
761
|
+
return null;
|
|
731
762
|
const trimmed = str.trim();
|
|
732
|
-
if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
|
|
763
|
+
if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
|
|
764
|
+
return null;
|
|
733
765
|
const content = trimmed.slice(1, -1).trim();
|
|
734
|
-
if (!content)
|
|
766
|
+
if (!content)
|
|
767
|
+
return [];
|
|
735
768
|
const result = [];
|
|
736
769
|
let depth = 0;
|
|
737
770
|
let current = "";
|
|
@@ -773,15 +806,21 @@ function parseLispList(str) {
|
|
|
773
806
|
}
|
|
774
807
|
current += ch;
|
|
775
808
|
}
|
|
776
|
-
if (current.trim())
|
|
809
|
+
if (current.trim())
|
|
810
|
+
result.push(current.trim());
|
|
777
811
|
return result.map((item) => {
|
|
778
812
|
const t = item.trim();
|
|
779
|
-
if (t === "nil")
|
|
780
|
-
|
|
781
|
-
if (t === "
|
|
813
|
+
if (t === "nil")
|
|
814
|
+
return null;
|
|
815
|
+
if (t === "t")
|
|
816
|
+
return true;
|
|
817
|
+
if (t === "T")
|
|
818
|
+
return true;
|
|
782
819
|
const num = Number(t);
|
|
783
|
-
if (!isNaN(num) && t !== "")
|
|
784
|
-
|
|
820
|
+
if (!isNaN(num) && t !== "")
|
|
821
|
+
return num;
|
|
822
|
+
if (t.startsWith('"') && t.endsWith('"'))
|
|
823
|
+
return t.slice(1, -1);
|
|
785
824
|
return t;
|
|
786
825
|
});
|
|
787
826
|
}
|
|
@@ -796,14 +835,16 @@ var RESOURCES = [
|
|
|
796
835
|
];
|
|
797
836
|
function parseQuery(uri) {
|
|
798
837
|
const qIdx = uri.indexOf("?");
|
|
799
|
-
if (qIdx === -1)
|
|
838
|
+
if (qIdx === -1)
|
|
839
|
+
return { base: uri, params: {} };
|
|
800
840
|
const base = uri.substring(0, qIdx);
|
|
801
841
|
const params = {};
|
|
802
842
|
uri.substring(qIdx + 1).split("&").forEach((p) => {
|
|
803
843
|
const eqIdx = p.indexOf("=");
|
|
804
844
|
const k = eqIdx === -1 ? p : p.substring(0, eqIdx);
|
|
805
845
|
const v = eqIdx === -1 ? "" : p.substring(eqIdx + 1);
|
|
806
|
-
if (k)
|
|
846
|
+
if (k)
|
|
847
|
+
params[k] = decodeURIComponent(v);
|
|
807
848
|
});
|
|
808
849
|
return { base, params };
|
|
809
850
|
}
|
|
@@ -839,7 +880,8 @@ async function readResource(uri) {
|
|
|
839
880
|
}
|
|
840
881
|
async function getCadInfo2() {
|
|
841
882
|
const cached = getCached("cad:info");
|
|
842
|
-
if (cached)
|
|
883
|
+
if (cached)
|
|
884
|
+
return cached;
|
|
843
885
|
if (!cad.connected) {
|
|
844
886
|
await cad.connect();
|
|
845
887
|
}
|
|
@@ -866,9 +908,12 @@ async function getCadInfo2() {
|
|
|
866
908
|
async function getLayers(filterName = null) {
|
|
867
909
|
const cacheKey = filterName ? `layers:${filterName}` : "layers:all";
|
|
868
910
|
const cached = getCached(cacheKey);
|
|
869
|
-
if (cached)
|
|
870
|
-
|
|
871
|
-
if (!cad.connected)
|
|
911
|
+
if (cached)
|
|
912
|
+
return cached;
|
|
913
|
+
if (!cad.connected)
|
|
914
|
+
await cad.connect();
|
|
915
|
+
if (!cad.connected)
|
|
916
|
+
return [];
|
|
872
917
|
try {
|
|
873
918
|
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))`;
|
|
874
919
|
const result = await cad.sendCommandWithResult(code);
|
|
@@ -915,8 +960,10 @@ async function getLayers(filterName = null) {
|
|
|
915
960
|
async function getEntities(filterType = null) {
|
|
916
961
|
const cacheKey = filterType ? `entities:${filterType}` : "entities:all";
|
|
917
962
|
const cached = getCached(cacheKey);
|
|
918
|
-
if (cached)
|
|
919
|
-
|
|
963
|
+
if (cached)
|
|
964
|
+
return cached;
|
|
965
|
+
if (!cad.connected)
|
|
966
|
+
await cad.connect();
|
|
920
967
|
if (!cad.connected) {
|
|
921
968
|
const result = { total: 0, byType: {} };
|
|
922
969
|
setCache(cacheKey, result);
|
|
@@ -970,8 +1017,10 @@ async function getEntities(filterType = null) {
|
|
|
970
1017
|
}
|
|
971
1018
|
}
|
|
972
1019
|
async function getDwgName() {
|
|
973
|
-
if (!cad.connected)
|
|
974
|
-
|
|
1020
|
+
if (!cad.connected)
|
|
1021
|
+
await cad.connect();
|
|
1022
|
+
if (!cad.connected)
|
|
1023
|
+
return { name: null };
|
|
975
1024
|
try {
|
|
976
1025
|
const code = `(vl-princ-to-string (getvar "dwgname"))`;
|
|
977
1026
|
const name = await cad.sendCommandWithResult(code);
|
|
@@ -981,8 +1030,10 @@ async function getDwgName() {
|
|
|
981
1030
|
}
|
|
982
1031
|
}
|
|
983
1032
|
async function getDwgPath() {
|
|
984
|
-
if (!cad.connected)
|
|
985
|
-
|
|
1033
|
+
if (!cad.connected)
|
|
1034
|
+
await cad.connect();
|
|
1035
|
+
if (!cad.connected)
|
|
1036
|
+
return { path: null, name: null };
|
|
986
1037
|
try {
|
|
987
1038
|
const code = `(progn
|
|
988
1039
|
(setq prefix (vl-princ-to-string (getvar "dwgprefix")))
|
|
@@ -1000,7 +1051,8 @@ async function getDwgPath() {
|
|
|
1000
1051
|
}
|
|
1001
1052
|
if (!parsed) {
|
|
1002
1053
|
const listResult = parseLispList(result);
|
|
1003
|
-
if (listResult && listResult.length >= 2)
|
|
1054
|
+
if (listResult && listResult.length >= 2)
|
|
1055
|
+
parsed = listResult;
|
|
1004
1056
|
}
|
|
1005
1057
|
if (parsed && Array.isArray(parsed) && parsed.length >= 2) {
|
|
1006
1058
|
return { path: String(parsed[0]), name: String(parsed[1]) };
|
|
@@ -1204,10 +1256,14 @@ ${generateSuggestions(entities, layers)}`
|
|
|
1204
1256
|
}
|
|
1205
1257
|
function generateSuggestions(entities, layers) {
|
|
1206
1258
|
const suggestions = [];
|
|
1207
|
-
if (entities.total > 1e3)
|
|
1208
|
-
|
|
1209
|
-
if (
|
|
1210
|
-
|
|
1259
|
+
if (entities.total > 1e3)
|
|
1260
|
+
suggestions.push("- \u56FE\u7EB8\u5B9E\u4F53\u8F83\u591A\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u56FE\u5C42\u5206\u7C7B\u7BA1\u7406");
|
|
1261
|
+
if (layers.length > 20)
|
|
1262
|
+
suggestions.push("- \u56FE\u5C42\u8F83\u591A\uFF0C\u5EFA\u8BAE\u6E05\u7406\u672A\u4F7F\u7528\u7684\u56FE\u5C42");
|
|
1263
|
+
if (entities.byType.LINE && entities.byType.LINE > 500)
|
|
1264
|
+
suggestions.push("- \u7EBF\u6761\u8F83\u591A\uFF0C\u53EF\u8003\u8651\u4F7F\u7528 BLOCK \u51CF\u5C11\u5B9E\u4F53\u6570\u91CF");
|
|
1265
|
+
if (!entities.byType.DIMENSION)
|
|
1266
|
+
suggestions.push("- \u672A\u53D1\u73B0\u5C3A\u5BF8\u6807\u6CE8\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u6807\u6CE8");
|
|
1211
1267
|
return suggestions.length ? suggestions.join("\n") : "- \u56FE\u7EB8\u7ED3\u6784\u826F\u597D";
|
|
1212
1268
|
}
|
|
1213
1269
|
async function generateBatchLinesPrompt(args) {
|
|
@@ -1523,9 +1579,11 @@ var SseSession = class {
|
|
|
1523
1579
|
return lines.join("\n") + "\n\n";
|
|
1524
1580
|
}
|
|
1525
1581
|
_setupDrain() {
|
|
1526
|
-
if (typeof this.#res.on !== "function")
|
|
1582
|
+
if (typeof this.#res.on !== "function")
|
|
1583
|
+
return;
|
|
1527
1584
|
this.#drainHandler = () => {
|
|
1528
|
-
if (!this.#active)
|
|
1585
|
+
if (!this.#active)
|
|
1586
|
+
return;
|
|
1529
1587
|
if (this.#backpressureBuffer.length > 0) {
|
|
1530
1588
|
this._drainBuffer();
|
|
1531
1589
|
}
|
|
@@ -1547,7 +1605,8 @@ var SseSession = class {
|
|
|
1547
1605
|
}
|
|
1548
1606
|
}
|
|
1549
1607
|
_write(content) {
|
|
1550
|
-
if (!this.#active)
|
|
1608
|
+
if (!this.#active)
|
|
1609
|
+
return false;
|
|
1551
1610
|
try {
|
|
1552
1611
|
if (this.#backpressureBuffer.length > 0) {
|
|
1553
1612
|
this.#backpressureBuffer.push(content);
|
|
@@ -1817,7 +1876,8 @@ var SERVER_CAPABILITIES = {
|
|
|
1817
1876
|
prompts: {}
|
|
1818
1877
|
};
|
|
1819
1878
|
var { port, host, transport, apiKey, rateLimitWindow, rateLimitMax } = config_default;
|
|
1820
|
-
if (apiKey)
|
|
1879
|
+
if (apiKey)
|
|
1880
|
+
log("API Key authentication enabled");
|
|
1821
1881
|
var mcpLimiter = rateLimit({
|
|
1822
1882
|
windowMs: rateLimitWindow,
|
|
1823
1883
|
max: rateLimitMax,
|
|
@@ -1864,12 +1924,13 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
1864
1924
|
install_atlisp: () => installAtlisp(),
|
|
1865
1925
|
init_atlisp: () => initAtlisp(),
|
|
1866
1926
|
get_function_usage: (a) => getFunctionUsage(a.name, a.package),
|
|
1867
|
-
list_symbols: (a) =>
|
|
1927
|
+
list_symbols: (a) => listSymbols(a.package),
|
|
1868
1928
|
import_funlib: async (a) => {
|
|
1869
1929
|
const data = await loadAtlibFunctionLib();
|
|
1870
|
-
if (!data)
|
|
1930
|
+
if (!data)
|
|
1931
|
+
return { content: [{ type: "text", text: "\u52A0\u8F7D\u51FD\u6570\u5E93\u5931\u8D25" }], isError: true };
|
|
1871
1932
|
if (a.format === "list") {
|
|
1872
|
-
const items = data.
|
|
1933
|
+
const items = Object.values(data.all_functions || {}).map((f) => `${f.name}: ${f.description || ""}`);
|
|
1873
1934
|
return { content: [{ type: "text", text: items.join("\n") }] };
|
|
1874
1935
|
}
|
|
1875
1936
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
@@ -2029,7 +2090,8 @@ var tools = [
|
|
|
2029
2090
|
];
|
|
2030
2091
|
async function handleToolCall(name, args) {
|
|
2031
2092
|
const handler = TOOL_HANDLERS[name];
|
|
2032
|
-
if (!handler)
|
|
2093
|
+
if (!handler)
|
|
2094
|
+
return { content: [{ type: "text", text: `\u672A\u77E5\u5DE5\u5177: ${name}` }], isError: true };
|
|
2033
2095
|
try {
|
|
2034
2096
|
const result = await handler(args || {});
|
|
2035
2097
|
notifyResourceChanges(name);
|
|
@@ -2150,7 +2212,8 @@ async function startServer() {
|
|
|
2150
2212
|
const JSON_CONTENT_TYPES = ["application/json", "application/json-rpc", "application/vnd.api+json"];
|
|
2151
2213
|
app.use(async (req, res, next) => {
|
|
2152
2214
|
const ct = (req.headers["content-type"] || "").toLowerCase();
|
|
2153
|
-
if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
|
|
2215
|
+
if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
|
|
2216
|
+
return next();
|
|
2154
2217
|
try {
|
|
2155
2218
|
const buf = await rawBody(req, { limit: "10mb" });
|
|
2156
2219
|
const m = ct.match(/charset\s*=\s*([^\s;]+)/i);
|
|
@@ -2171,9 +2234,11 @@ async function startServer() {
|
|
|
2171
2234
|
const PUBLIC_PATHS = ["/health"];
|
|
2172
2235
|
if (apiKey) {
|
|
2173
2236
|
app.use((req, res, next) => {
|
|
2174
|
-
if (PUBLIC_PATHS.includes(req.path))
|
|
2237
|
+
if (PUBLIC_PATHS.includes(req.path))
|
|
2238
|
+
return next();
|
|
2175
2239
|
const auth = req.get("Authorization");
|
|
2176
|
-
if (auth === `Bearer ${apiKey}`)
|
|
2240
|
+
if (auth === `Bearer ${apiKey}`)
|
|
2241
|
+
return next();
|
|
2177
2242
|
res.status(401).json({ error: "Unauthorized" });
|
|
2178
2243
|
});
|
|
2179
2244
|
}
|
|
@@ -2188,7 +2253,8 @@ async function startServer() {
|
|
|
2188
2253
|
res.setHeader("Access-Control-Expose-Headers", "mcp-session-id, content-type, x-accel-buffering");
|
|
2189
2254
|
res.setHeader("Access-Control-Max-Age", "86400");
|
|
2190
2255
|
res.setHeader("Vary", "Accept");
|
|
2191
|
-
if (req.method === "OPTIONS")
|
|
2256
|
+
if (req.method === "OPTIONS")
|
|
2257
|
+
return res.status(204).end();
|
|
2192
2258
|
next();
|
|
2193
2259
|
});
|
|
2194
2260
|
}
|
package/dist/cad-worker.js
CHANGED
|
@@ -154,7 +154,7 @@ const cadSendWithResult = edge.func(function() {/*
|
|
|
154
154
|
dynamic doc = cad.ActiveDocument;
|
|
155
155
|
if (doc != null) {
|
|
156
156
|
// 加载 .lsp 文件执行
|
|
157
|
-
doc.SendCommand("
|
|
157
|
+
doc.SendCommand("(load \"" + lispFile.Replace("\\", "\\\\") + "\")\n");
|
|
158
158
|
|
|
159
159
|
int retries = 10;
|
|
160
160
|
string result = "";
|
|
@@ -440,21 +440,29 @@ async function handleMessage(msg) {
|
|
|
440
440
|
if (!parenCheck.valid) {
|
|
441
441
|
return { success: false, error: `括号错误: ${parenCheck.error} (位置 ${parenCheck.pos})` };
|
|
442
442
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
443
|
+
const maxRetries = 3;
|
|
444
|
+
let lastError = null;
|
|
445
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
446
|
+
const isBusy = await waitForIdle(msg.platform || 'AutoCAD');
|
|
447
|
+
if (isBusy) {
|
|
448
|
+
log(`send: ${msg.code}`);
|
|
449
|
+
try {
|
|
450
|
+
const r = await new Promise((resolve, reject) => {
|
|
451
|
+
cadSend({ code: msg.code, platform: msg.platform }, (e, r) => {
|
|
452
|
+
if (e) reject(e);
|
|
453
|
+
else resolve(r);
|
|
454
|
+
});
|
|
455
|
+
});
|
|
453
456
|
log(`send result: ${JSON.stringify(r)}`);
|
|
454
|
-
|
|
457
|
+
return r;
|
|
458
|
+
} catch (e) {
|
|
459
|
+
log(`send error: ${e.message}`);
|
|
460
|
+
lastError = e;
|
|
455
461
|
}
|
|
456
|
-
}
|
|
457
|
-
|
|
462
|
+
}
|
|
463
|
+
await new Promise(r => setTimeout(r, 500));
|
|
464
|
+
}
|
|
465
|
+
return { success: false, error: lastError?.message || '发送失败' };
|
|
458
466
|
}
|
|
459
467
|
if (msg.type === 'sendResult') {
|
|
460
468
|
const docCheck = await new Promise((resolve, reject) => {
|
|
@@ -470,21 +478,29 @@ async function handleMessage(msg) {
|
|
|
470
478
|
if (!parenCheck.valid) {
|
|
471
479
|
return { success: false, error: `括号错误: ${parenCheck.error} (位置 ${parenCheck.pos})` };
|
|
472
480
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
481
|
+
const maxRetriesResult = 3;
|
|
482
|
+
let lastErrorResult = null;
|
|
483
|
+
for (let i = 0; i < maxRetriesResult; i++) {
|
|
484
|
+
const isBusy = await waitForIdle(msg.platform);
|
|
485
|
+
if (isBusy) {
|
|
486
|
+
log(`sendResult: ${msg.code}`);
|
|
487
|
+
try {
|
|
488
|
+
const r = await new Promise((resolve, reject) => {
|
|
489
|
+
cadSendWithResult({ code: msg.code, platform: msg.platform, encoding: msg.encoding || '' }, (e, r) => {
|
|
490
|
+
if (e) reject(e);
|
|
491
|
+
else resolve(r);
|
|
492
|
+
});
|
|
493
|
+
});
|
|
483
494
|
log(`sendResult result: ${JSON.stringify(r)}`);
|
|
484
|
-
|
|
495
|
+
return r;
|
|
496
|
+
} catch (e) {
|
|
497
|
+
log(`sendResult error: ${e.message}`);
|
|
498
|
+
lastErrorResult = e;
|
|
485
499
|
}
|
|
486
|
-
}
|
|
487
|
-
|
|
500
|
+
}
|
|
501
|
+
await new Promise(r => setTimeout(r, 500));
|
|
502
|
+
}
|
|
503
|
+
return { success: false, error: lastErrorResult?.message || '发送失败' };
|
|
488
504
|
}
|
|
489
505
|
if (msg.type === 'isBusy') {
|
|
490
506
|
return new Promise((resolve, reject) => {
|