@atlisp/mcp 1.3.8 → 1.4.1
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 +325 -175
- package/package.json +1 -1
package/dist/atlisp-mcp.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/atlisp-mcp.js
|
|
4
|
-
import
|
|
5
|
-
import { fileURLToPath as
|
|
4
|
+
import path5 from "path";
|
|
5
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
6
6
|
import { createRequire } from "module";
|
|
7
7
|
import express from "express";
|
|
8
8
|
import rawBody from "raw-body";
|
|
@@ -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;
|
|
@@ -117,7 +119,7 @@ var FILE_EXTENSIONS = {
|
|
|
117
119
|
"BricsCAD": [".des"]
|
|
118
120
|
};
|
|
119
121
|
var SERVER_NAME = "atlisp-mcp-server";
|
|
120
|
-
var SERVER_VERSION = "1.
|
|
122
|
+
var SERVER_VERSION = "1.4.0";
|
|
121
123
|
var MOCK_PACKAGES = [
|
|
122
124
|
{ name: "base", description: "\u57FA\u7840\u51FD\u6570\u5E93", version: "1.0.0" },
|
|
123
125
|
{ name: "at-pm", description: "\u5DE5\u7A0B\u9879\u76EE\u7BA1\u7406", version: "2.1.0" },
|
|
@@ -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() {
|
|
@@ -455,7 +470,8 @@ async function evalLisp(code, withResult = false, encoding = null) {
|
|
|
455
470
|
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
456
471
|
}
|
|
457
472
|
const trimmed = (code || "").trim();
|
|
458
|
-
if (!trimmed)
|
|
473
|
+
if (!trimmed)
|
|
474
|
+
return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
|
|
459
475
|
try {
|
|
460
476
|
if (withResult) {
|
|
461
477
|
const result = await cad.sendCommandWithResult(trimmed, encoding);
|
|
@@ -475,14 +491,17 @@ async function getCadInfo() {
|
|
|
475
491
|
if (!cad.connected) {
|
|
476
492
|
await cad.connect();
|
|
477
493
|
}
|
|
478
|
-
if (!cad.connected)
|
|
494
|
+
if (!cad.connected)
|
|
495
|
+
return { content: [{ type: "text", text: "CAD \u672A\u8FDE\u63A5" }] };
|
|
479
496
|
const info = await cad.getInfo();
|
|
480
497
|
return { content: [{ type: "text", text: info }] };
|
|
481
498
|
}
|
|
482
499
|
async function atCommand(command) {
|
|
483
|
-
if (!cad.connected)
|
|
500
|
+
if (!cad.connected)
|
|
501
|
+
return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
|
|
484
502
|
const trimmed = (command || "").trim();
|
|
485
|
-
if (!trimmed)
|
|
503
|
+
if (!trimmed)
|
|
504
|
+
return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
|
|
486
505
|
await cad.sendCommand(trimmed + "\n");
|
|
487
506
|
return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001\u547D\u4EE4" }] };
|
|
488
507
|
}
|
|
@@ -490,7 +509,8 @@ async function newDocument() {
|
|
|
490
509
|
if (!cad.connected) {
|
|
491
510
|
await cad.connect();
|
|
492
511
|
}
|
|
493
|
-
if (!cad.connected)
|
|
512
|
+
if (!cad.connected)
|
|
513
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
494
514
|
const result = await cad.newDoc();
|
|
495
515
|
if (result) {
|
|
496
516
|
return { content: [{ type: "text", text: "\u5DF2\u5728 CAD \u4E2D\u65B0\u5EFA\u7A7A\u767D\u6587\u6863" }] };
|
|
@@ -501,7 +521,8 @@ async function bringToFront() {
|
|
|
501
521
|
if (!cad.connected) {
|
|
502
522
|
await cad.connect();
|
|
503
523
|
}
|
|
504
|
-
if (!cad.connected)
|
|
524
|
+
if (!cad.connected)
|
|
525
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
505
526
|
const result = await cad.bringToFront();
|
|
506
527
|
if (result) {
|
|
507
528
|
return { content: [{ type: "text", text: "\u5DF2\u5C06 CAD \u7A97\u53E3\u5207\u6362\u5230\u524D\u53F0" }] };
|
|
@@ -512,7 +533,8 @@ async function installAtlisp() {
|
|
|
512
533
|
if (!cad.connected) {
|
|
513
534
|
await cad.connect();
|
|
514
535
|
}
|
|
515
|
-
if (!cad.connected)
|
|
536
|
+
if (!cad.connected)
|
|
537
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
516
538
|
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))))`;
|
|
517
539
|
await cad.sendCommand(installCode + "\n");
|
|
518
540
|
return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001 @lisp \u5B89\u88C5\u4EE3\u7801\u5230 CAD" }] };
|
|
@@ -521,20 +543,68 @@ async function listFunctionsInCad() {
|
|
|
521
543
|
if (!cad.connected) {
|
|
522
544
|
await cad.connect();
|
|
523
545
|
}
|
|
524
|
-
if (!cad.connected)
|
|
546
|
+
if (!cad.connected)
|
|
547
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
525
548
|
try {
|
|
526
549
|
const result = await cad.sendCommandWithResult("(atoms-family 0)", null);
|
|
527
|
-
if (result)
|
|
550
|
+
if (result)
|
|
551
|
+
return { content: [{ type: "text", text: result }] };
|
|
528
552
|
return { content: [{ type: "text", text: "CAD \u51FD\u6570\u5217\u8868\u4E3A\u7A7A" }] };
|
|
529
553
|
} catch (e) {
|
|
530
554
|
return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
|
|
531
555
|
}
|
|
532
556
|
}
|
|
557
|
+
async function getSystemStatus() {
|
|
558
|
+
const status = {
|
|
559
|
+
mcp: { version: process.env.npm_package_version || "unknown" },
|
|
560
|
+
worker: { alive: false },
|
|
561
|
+
cad: { connected: false, platform: null, version: null, busy: false, hasDoc: false },
|
|
562
|
+
lisp: { available: false, testResult: null, error: null },
|
|
563
|
+
packages: null
|
|
564
|
+
};
|
|
565
|
+
try {
|
|
566
|
+
status.worker.alive = await cad.ping();
|
|
567
|
+
} catch {
|
|
568
|
+
status.worker.alive = false;
|
|
569
|
+
}
|
|
570
|
+
status.cad.connected = cad.connected;
|
|
571
|
+
if (cad.connected) {
|
|
572
|
+
status.cad.platform = cad.getPlatform();
|
|
573
|
+
status.cad.version = cad.getVersion();
|
|
574
|
+
try {
|
|
575
|
+
status.cad.busy = await cad.isBusy();
|
|
576
|
+
} catch {
|
|
577
|
+
}
|
|
578
|
+
try {
|
|
579
|
+
const doc = await cad.hasDoc();
|
|
580
|
+
status.cad.hasDoc = doc.hasDoc;
|
|
581
|
+
} catch {
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
const r = await cad.sendCommandWithResult("(+ 1 2)");
|
|
585
|
+
if (r !== null && r !== void 0) {
|
|
586
|
+
status.lisp.available = true;
|
|
587
|
+
status.lisp.testResult = String(r).trim();
|
|
588
|
+
}
|
|
589
|
+
} catch (e) {
|
|
590
|
+
status.lisp.error = e.message;
|
|
591
|
+
}
|
|
592
|
+
try {
|
|
593
|
+
const pkgResult = await cad.sendCommandWithResult("(@::package-list-in-local)");
|
|
594
|
+
if (pkgResult && pkgResult !== "nil") {
|
|
595
|
+
status.packages = pkgResult;
|
|
596
|
+
}
|
|
597
|
+
} catch {
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return { content: [{ type: "text", text: JSON.stringify(status, null, 2) }] };
|
|
601
|
+
}
|
|
533
602
|
async function initAtlisp() {
|
|
534
603
|
if (!cad.connected) {
|
|
535
604
|
await cad.connect();
|
|
536
605
|
}
|
|
537
|
-
if (!cad.connected)
|
|
606
|
+
if (!cad.connected)
|
|
607
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
538
608
|
const code = `(if (null @::load-module)
|
|
539
609
|
(progn
|
|
540
610
|
(vl-load-com)
|
|
@@ -574,10 +644,13 @@ async function fetchPackages() {
|
|
|
574
644
|
return null;
|
|
575
645
|
}
|
|
576
646
|
async function listPackages() {
|
|
577
|
-
if (!cad.connected)
|
|
578
|
-
|
|
647
|
+
if (!cad.connected)
|
|
648
|
+
await cad.connect();
|
|
649
|
+
if (!cad.connected)
|
|
650
|
+
return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
|
|
579
651
|
const result = await cad.sendCommandWithResult("(@::package-list-in-local)");
|
|
580
|
-
if (result && result !== "nil")
|
|
652
|
+
if (result && result !== "nil")
|
|
653
|
+
return { content: [{ type: "text", text: result }] };
|
|
581
654
|
const packages = MOCK_PACKAGES.map((p) => `${p.name} v${p.version} - ${p.description}`);
|
|
582
655
|
return { content: [{ type: "text", text: `\u5DF2\u5B89\u88C5\u7684 @lisp \u5305:
|
|
583
656
|
${packages.join("\n")}` }] };
|
|
@@ -594,10 +667,12 @@ async function searchPackages(query) {
|
|
|
594
667
|
for (const p of items) {
|
|
595
668
|
const name = (p.name || "").toLowerCase();
|
|
596
669
|
const desc = (p.description || "").toLowerCase();
|
|
597
|
-
if (name.includes(q) || desc.includes(q))
|
|
670
|
+
if (name.includes(q) || desc.includes(q))
|
|
671
|
+
results.push(p);
|
|
598
672
|
}
|
|
599
673
|
} else {
|
|
600
|
-
for (const p of items)
|
|
674
|
+
for (const p of items)
|
|
675
|
+
results.push(p);
|
|
601
676
|
}
|
|
602
677
|
if (results.length === 0) {
|
|
603
678
|
return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5305\u542B "${query}" \u7684\u5305` }] };
|
|
@@ -639,7 +714,8 @@ async function getFunctionUsage(funcName, packageName) {
|
|
|
639
714
|
const data = await response.json();
|
|
640
715
|
const funcs = Object.values(data.all_functions || {});
|
|
641
716
|
const func = funcs.find((f2) => f2.name === funcName || f2.name === `${packageName}:${funcName}`);
|
|
642
|
-
if (func)
|
|
717
|
+
if (func)
|
|
718
|
+
results.push(func);
|
|
643
719
|
}
|
|
644
720
|
} catch (e) {
|
|
645
721
|
log(`function-handlers fetch error: ${e.message}`);
|
|
@@ -650,7 +726,8 @@ async function getFunctionUsage(funcName, packageName) {
|
|
|
650
726
|
const raw = await fs2.readFile(path3.join(FUNCTIONS_DIR, file), "utf-8");
|
|
651
727
|
const data = JSON.parse(raw);
|
|
652
728
|
const func = data.functions?.find((f2) => f2.name === funcName);
|
|
653
|
-
if (func)
|
|
729
|
+
if (func)
|
|
730
|
+
results.push(func);
|
|
654
731
|
}
|
|
655
732
|
}
|
|
656
733
|
if (results.length === 0) {
|
|
@@ -717,6 +794,11 @@ ${allFuncs.map((f) => f.name).join("\n")}` }] };
|
|
|
717
794
|
}
|
|
718
795
|
|
|
719
796
|
// src/handlers/resource-handlers.js
|
|
797
|
+
import fs3 from "fs";
|
|
798
|
+
import path4 from "path";
|
|
799
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
800
|
+
var __dirname2 = path4.dirname(fileURLToPath2(import.meta.url));
|
|
801
|
+
var STANDARDS_DIR = path4.join(__dirname2, "..", "standards");
|
|
720
802
|
var CACHE_TTL2 = config_default.resourceCacheTtl;
|
|
721
803
|
var resourceCache = /* @__PURE__ */ new Map();
|
|
722
804
|
function getCached(key) {
|
|
@@ -742,11 +824,14 @@ function clearCache(uri) {
|
|
|
742
824
|
}
|
|
743
825
|
}
|
|
744
826
|
function parseLispList(str) {
|
|
745
|
-
if (!str || typeof str !== "string")
|
|
827
|
+
if (!str || typeof str !== "string")
|
|
828
|
+
return null;
|
|
746
829
|
const trimmed = str.trim();
|
|
747
|
-
if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
|
|
830
|
+
if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
|
|
831
|
+
return null;
|
|
748
832
|
const content = trimmed.slice(1, -1).trim();
|
|
749
|
-
if (!content)
|
|
833
|
+
if (!content)
|
|
834
|
+
return [];
|
|
750
835
|
const result = [];
|
|
751
836
|
let depth = 0;
|
|
752
837
|
let current = "";
|
|
@@ -788,37 +873,48 @@ function parseLispList(str) {
|
|
|
788
873
|
}
|
|
789
874
|
current += ch;
|
|
790
875
|
}
|
|
791
|
-
if (current.trim())
|
|
876
|
+
if (current.trim())
|
|
877
|
+
result.push(current.trim());
|
|
792
878
|
return result.map((item) => {
|
|
793
879
|
const t = item.trim();
|
|
794
|
-
if (t === "nil")
|
|
795
|
-
|
|
796
|
-
if (t === "
|
|
880
|
+
if (t === "nil")
|
|
881
|
+
return null;
|
|
882
|
+
if (t === "t")
|
|
883
|
+
return true;
|
|
884
|
+
if (t === "T")
|
|
885
|
+
return true;
|
|
797
886
|
const num = Number(t);
|
|
798
|
-
if (!isNaN(num) && t !== "")
|
|
799
|
-
|
|
887
|
+
if (!isNaN(num) && t !== "")
|
|
888
|
+
return num;
|
|
889
|
+
if (t.startsWith('"') && t.endsWith('"'))
|
|
890
|
+
return t.slice(1, -1);
|
|
800
891
|
return t;
|
|
801
892
|
});
|
|
802
893
|
}
|
|
803
894
|
var RESOURCES = [
|
|
804
895
|
{ uri: "atlisp://cad/info", name: "CAD Info", description: "CAD \u8FDE\u63A5\u4FE1\u606F", mimeType: "application/json", subscribable: true },
|
|
805
|
-
{ uri: "atlisp://
|
|
806
|
-
{ uri: "atlisp://
|
|
896
|
+
{ uri: "atlisp://dwg/layers", name: "Layers", description: "\u56FE\u5C42\u5217\u8868", mimeType: "application/json", subscribable: true },
|
|
897
|
+
{ uri: "atlisp://dwg/entities", name: "Entities", description: "\u5B9E\u4F53\u7EDF\u8BA1", mimeType: "application/json", subscribable: true },
|
|
807
898
|
{ uri: "atlisp://dwg/name", name: "DWG Name", description: "\u5F53\u524D DWG \u6587\u4EF6\u540D", mimeType: "application/json", subscribable: true },
|
|
808
899
|
{ uri: "atlisp://dwg/path", name: "DWG Path", description: "\u6587\u4EF6\u5B8C\u6574\u8DEF\u5F84", mimeType: "application/json", subscribable: true },
|
|
900
|
+
{ uri: "atlisp://cad/dwgs", name: "DWG List", description: "\u6240\u6709\u6253\u5F00\u7684 DWG \u6587\u4EF6\u5217\u8868", mimeType: "application/json", subscribable: true },
|
|
809
901
|
{ uri: "atlisp://packages", name: "Packages", description: "\u5DF2\u5B89\u88C5\u5305\u5217\u8868", mimeType: "application/json", subscribable: true },
|
|
810
|
-
{ uri: "atlisp://platforms", name: "Platforms", description: "\u652F\u6301\u7684\u5E73\u53F0\u4FE1\u606F", mimeType: "application/json", subscribable: false }
|
|
902
|
+
{ uri: "atlisp://platforms", name: "Platforms", description: "\u652F\u6301\u7684\u5E73\u53F0\u4FE1\u606F", mimeType: "application/json", subscribable: false },
|
|
903
|
+
{ uri: "atlisp://standards/drafting", name: "Drafting Standards", description: "CAD \u5236\u56FE\u89C4\u8303", mimeType: "application/json", subscribable: false },
|
|
904
|
+
{ uri: "atlisp://standards/coding", name: "Coding Standards", description: "@lisp \u7F16\u7801\u89C4\u8303", mimeType: "application/json", subscribable: false }
|
|
811
905
|
];
|
|
812
906
|
function parseQuery(uri) {
|
|
813
907
|
const qIdx = uri.indexOf("?");
|
|
814
|
-
if (qIdx === -1)
|
|
908
|
+
if (qIdx === -1)
|
|
909
|
+
return { base: uri, params: {} };
|
|
815
910
|
const base = uri.substring(0, qIdx);
|
|
816
911
|
const params = {};
|
|
817
912
|
uri.substring(qIdx + 1).split("&").forEach((p) => {
|
|
818
913
|
const eqIdx = p.indexOf("=");
|
|
819
914
|
const k = eqIdx === -1 ? p : p.substring(0, eqIdx);
|
|
820
915
|
const v = eqIdx === -1 ? "" : p.substring(eqIdx + 1);
|
|
821
|
-
if (k)
|
|
916
|
+
if (k)
|
|
917
|
+
params[k] = decodeURIComponent(v);
|
|
822
918
|
});
|
|
823
919
|
return { base, params };
|
|
824
920
|
}
|
|
@@ -836,25 +932,32 @@ async function readResource(uri) {
|
|
|
836
932
|
switch (base) {
|
|
837
933
|
case "atlisp://cad/info":
|
|
838
934
|
return await getCadInfo2();
|
|
839
|
-
case "atlisp://
|
|
935
|
+
case "atlisp://dwg/layers":
|
|
840
936
|
return await getLayers(params.name);
|
|
841
|
-
case "atlisp://
|
|
937
|
+
case "atlisp://dwg/entities":
|
|
842
938
|
return await getEntities(params.type);
|
|
843
939
|
case "atlisp://dwg/name":
|
|
844
940
|
return await getDwgName();
|
|
845
941
|
case "atlisp://dwg/path":
|
|
846
942
|
return await getDwgPath();
|
|
943
|
+
case "atlisp://cad/dwgs":
|
|
944
|
+
return await getDwgList();
|
|
847
945
|
case "atlisp://packages":
|
|
848
946
|
return await getPackages(params.name);
|
|
849
947
|
case "atlisp://platforms":
|
|
850
948
|
return getPlatforms();
|
|
949
|
+
case "atlisp://standards/drafting":
|
|
950
|
+
return getDraftingStandards();
|
|
951
|
+
case "atlisp://standards/coding":
|
|
952
|
+
return getCodingStandards();
|
|
851
953
|
default:
|
|
852
954
|
throw new Error(`\u8D44\u6E90\u4E0D\u5B58\u5728: ${uri}`);
|
|
853
955
|
}
|
|
854
956
|
}
|
|
855
957
|
async function getCadInfo2() {
|
|
856
958
|
const cached = getCached("cad:info");
|
|
857
|
-
if (cached)
|
|
959
|
+
if (cached)
|
|
960
|
+
return cached;
|
|
858
961
|
if (!cad.connected) {
|
|
859
962
|
await cad.connect();
|
|
860
963
|
}
|
|
@@ -879,11 +982,14 @@ async function getCadInfo2() {
|
|
|
879
982
|
return result;
|
|
880
983
|
}
|
|
881
984
|
async function getLayers(filterName = null) {
|
|
882
|
-
const cacheKey = filterName ? `layers:${filterName}` : "layers:all";
|
|
985
|
+
const cacheKey = filterName ? `dwg:layers:${filterName}` : "dwg:layers:all";
|
|
883
986
|
const cached = getCached(cacheKey);
|
|
884
|
-
if (cached)
|
|
885
|
-
|
|
886
|
-
if (!cad.connected)
|
|
987
|
+
if (cached)
|
|
988
|
+
return cached;
|
|
989
|
+
if (!cad.connected)
|
|
990
|
+
await cad.connect();
|
|
991
|
+
if (!cad.connected)
|
|
992
|
+
return [];
|
|
887
993
|
try {
|
|
888
994
|
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))`;
|
|
889
995
|
const result = await cad.sendCommandWithResult(code);
|
|
@@ -928,10 +1034,12 @@ async function getLayers(filterName = null) {
|
|
|
928
1034
|
}
|
|
929
1035
|
}
|
|
930
1036
|
async function getEntities(filterType = null) {
|
|
931
|
-
const cacheKey = filterType ? `entities:${filterType}` : "entities:all";
|
|
1037
|
+
const cacheKey = filterType ? `dwg:entities:${filterType}` : "dwg:entities:all";
|
|
932
1038
|
const cached = getCached(cacheKey);
|
|
933
|
-
if (cached)
|
|
934
|
-
|
|
1039
|
+
if (cached)
|
|
1040
|
+
return cached;
|
|
1041
|
+
if (!cad.connected)
|
|
1042
|
+
await cad.connect();
|
|
935
1043
|
if (!cad.connected) {
|
|
936
1044
|
const result = { total: 0, byType: {} };
|
|
937
1045
|
setCache(cacheKey, result);
|
|
@@ -985,8 +1093,10 @@ async function getEntities(filterType = null) {
|
|
|
985
1093
|
}
|
|
986
1094
|
}
|
|
987
1095
|
async function getDwgName() {
|
|
988
|
-
if (!cad.connected)
|
|
989
|
-
|
|
1096
|
+
if (!cad.connected)
|
|
1097
|
+
await cad.connect();
|
|
1098
|
+
if (!cad.connected)
|
|
1099
|
+
return { name: null };
|
|
990
1100
|
try {
|
|
991
1101
|
const code = `(vl-princ-to-string (getvar "dwgname"))`;
|
|
992
1102
|
const name = await cad.sendCommandWithResult(code);
|
|
@@ -996,8 +1106,10 @@ async function getDwgName() {
|
|
|
996
1106
|
}
|
|
997
1107
|
}
|
|
998
1108
|
async function getDwgPath() {
|
|
999
|
-
if (!cad.connected)
|
|
1000
|
-
|
|
1109
|
+
if (!cad.connected)
|
|
1110
|
+
await cad.connect();
|
|
1111
|
+
if (!cad.connected)
|
|
1112
|
+
return { path: null, name: null };
|
|
1001
1113
|
try {
|
|
1002
1114
|
const code = `(progn
|
|
1003
1115
|
(setq prefix (vl-princ-to-string (getvar "dwgprefix")))
|
|
@@ -1015,7 +1127,8 @@ async function getDwgPath() {
|
|
|
1015
1127
|
}
|
|
1016
1128
|
if (!parsed) {
|
|
1017
1129
|
const listResult = parseLispList(result);
|
|
1018
|
-
if (listResult && listResult.length >= 2)
|
|
1130
|
+
if (listResult && listResult.length >= 2)
|
|
1131
|
+
parsed = listResult;
|
|
1019
1132
|
}
|
|
1020
1133
|
if (parsed && Array.isArray(parsed) && parsed.length >= 2) {
|
|
1021
1134
|
return { path: String(parsed[0]), name: String(parsed[1]) };
|
|
@@ -1028,9 +1141,12 @@ async function getDwgPath() {
|
|
|
1028
1141
|
async function getPackages(filterName = null) {
|
|
1029
1142
|
const cacheKey = filterName ? `packages:${filterName}` : "packages:all";
|
|
1030
1143
|
const cached = getCached(cacheKey);
|
|
1031
|
-
if (cached)
|
|
1032
|
-
|
|
1033
|
-
if (!cad.connected)
|
|
1144
|
+
if (cached)
|
|
1145
|
+
return cached;
|
|
1146
|
+
if (!cad.connected)
|
|
1147
|
+
await cad.connect();
|
|
1148
|
+
if (!cad.connected)
|
|
1149
|
+
return [];
|
|
1034
1150
|
try {
|
|
1035
1151
|
const code = `(mapcar 'cdr @::*local-pkgs*)`;
|
|
1036
1152
|
const result = await cad.sendCommandWithResult(code);
|
|
@@ -1044,7 +1160,8 @@ async function getPackages(filterName = null) {
|
|
|
1044
1160
|
} catch {
|
|
1045
1161
|
raw = parseLispList(result) || [];
|
|
1046
1162
|
}
|
|
1047
|
-
if (!Array.isArray(raw))
|
|
1163
|
+
if (!Array.isArray(raw))
|
|
1164
|
+
raw = [];
|
|
1048
1165
|
const packages = raw.map((item) => {
|
|
1049
1166
|
if (Array.isArray(item)) {
|
|
1050
1167
|
const pkg = { name: "", version: "0.0.0", description: "", loaded: true };
|
|
@@ -1053,13 +1170,20 @@ async function getPackages(filterName = null) {
|
|
|
1053
1170
|
const [[key, val]] = Object.entries(entry);
|
|
1054
1171
|
const k = String(key);
|
|
1055
1172
|
const v = String(val);
|
|
1056
|
-
if (k === ":NAME")
|
|
1057
|
-
|
|
1058
|
-
else if (k === ":
|
|
1059
|
-
|
|
1060
|
-
else if (k === ":
|
|
1061
|
-
|
|
1062
|
-
else if (k === ":
|
|
1173
|
+
if (k === ":NAME")
|
|
1174
|
+
pkg.name = v;
|
|
1175
|
+
else if (k === ":VERSION")
|
|
1176
|
+
pkg.version = v;
|
|
1177
|
+
else if (k === ":DESCRIPTION")
|
|
1178
|
+
pkg.description = v;
|
|
1179
|
+
else if (k === ":FULL-NAME")
|
|
1180
|
+
pkg.fullName = v;
|
|
1181
|
+
else if (k === ":AUTHOR")
|
|
1182
|
+
pkg.author = v;
|
|
1183
|
+
else if (k === ":CATEGORY")
|
|
1184
|
+
pkg.category = v;
|
|
1185
|
+
else if (k === ":URL")
|
|
1186
|
+
pkg.url = v;
|
|
1063
1187
|
}
|
|
1064
1188
|
}
|
|
1065
1189
|
return pkg;
|
|
@@ -1087,26 +1211,95 @@ function getPlatforms() {
|
|
|
1087
1211
|
extensions: FILE_EXTENSIONS[name] || []
|
|
1088
1212
|
}));
|
|
1089
1213
|
}
|
|
1214
|
+
async function getDwgList() {
|
|
1215
|
+
const cacheKey = "cad:dwgs";
|
|
1216
|
+
const cached = getCached(cacheKey);
|
|
1217
|
+
if (cached)
|
|
1218
|
+
return cached;
|
|
1219
|
+
if (!cad.connected)
|
|
1220
|
+
await cad.connect();
|
|
1221
|
+
if (!cad.connected)
|
|
1222
|
+
return [];
|
|
1223
|
+
try {
|
|
1224
|
+
const code = `(progn
|
|
1225
|
+
(vl-load-com)
|
|
1226
|
+
(setq result nil)
|
|
1227
|
+
(vlax-for doc (vla-get-Documents (vla-get-Application (vlax-get-acad-object)))
|
|
1228
|
+
(setq result (cons (list (vla-get-Name doc) (vla-get-FullName doc)) result))
|
|
1229
|
+
)
|
|
1230
|
+
(reverse result)
|
|
1231
|
+
)`;
|
|
1232
|
+
const result = await cad.sendCommandWithResult(code);
|
|
1233
|
+
if (!result || result === "" || result === "nil") {
|
|
1234
|
+
setCache(cacheKey, []);
|
|
1235
|
+
return [];
|
|
1236
|
+
}
|
|
1237
|
+
let parsed = [];
|
|
1238
|
+
try {
|
|
1239
|
+
parsed = JSON.parse(result);
|
|
1240
|
+
} catch (e) {
|
|
1241
|
+
const listResult = parseLispList(result);
|
|
1242
|
+
if (listResult) {
|
|
1243
|
+
parsed = listResult;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
if (!Array.isArray(parsed))
|
|
1247
|
+
parsed = [];
|
|
1248
|
+
const dwgList = parsed.map((item) => {
|
|
1249
|
+
if (Array.isArray(item) && item.length >= 2) {
|
|
1250
|
+
return { name: String(item[0]), path: String(item[1]) };
|
|
1251
|
+
}
|
|
1252
|
+
return null;
|
|
1253
|
+
}).filter(Boolean);
|
|
1254
|
+
setCache(cacheKey, dwgList);
|
|
1255
|
+
return dwgList;
|
|
1256
|
+
} catch (e) {
|
|
1257
|
+
setCache(cacheKey, []);
|
|
1258
|
+
return [];
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
function loadStandardsFile(filename) {
|
|
1262
|
+
const filePath = path4.join(STANDARDS_DIR, filename);
|
|
1263
|
+
try {
|
|
1264
|
+
const raw = fs3.readFileSync(filePath, "utf-8");
|
|
1265
|
+
return JSON.parse(raw);
|
|
1266
|
+
} catch (e) {
|
|
1267
|
+
log(`Error loading standards file ${filename}: ${e.message}`);
|
|
1268
|
+
return null;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
var standardsCache = /* @__PURE__ */ new Map();
|
|
1272
|
+
function getCachedStandards(key) {
|
|
1273
|
+
const entry = standardsCache.get(key);
|
|
1274
|
+
if (entry && Date.now() - entry.timestamp < 3e4)
|
|
1275
|
+
return entry.data;
|
|
1276
|
+
standardsCache.delete(key);
|
|
1277
|
+
return null;
|
|
1278
|
+
}
|
|
1279
|
+
function setCachedStandards(key, data) {
|
|
1280
|
+
standardsCache.set(key, { data, timestamp: Date.now() });
|
|
1281
|
+
}
|
|
1282
|
+
function getDraftingStandards() {
|
|
1283
|
+
const cached = getCachedStandards("drafting");
|
|
1284
|
+
if (cached)
|
|
1285
|
+
return cached;
|
|
1286
|
+
const data = loadStandardsFile("drafting.json");
|
|
1287
|
+
if (data)
|
|
1288
|
+
setCachedStandards("drafting", data);
|
|
1289
|
+
return data || { error: "\u5236\u56FE\u89C4\u8303\u6587\u4EF6\u52A0\u8F7D\u5931\u8D25" };
|
|
1290
|
+
}
|
|
1291
|
+
function getCodingStandards() {
|
|
1292
|
+
const cached = getCachedStandards("coding");
|
|
1293
|
+
if (cached)
|
|
1294
|
+
return cached;
|
|
1295
|
+
const data = loadStandardsFile("coding.json");
|
|
1296
|
+
if (data)
|
|
1297
|
+
setCachedStandards("coding", data);
|
|
1298
|
+
return data || { error: "\u7F16\u7801\u89C4\u8303\u6587\u4EF6\u52A0\u8F7D\u5931\u8D25" };
|
|
1299
|
+
}
|
|
1090
1300
|
|
|
1091
1301
|
// src/handlers/prompt-handlers.js
|
|
1092
1302
|
var PROMPTS = [
|
|
1093
|
-
{
|
|
1094
|
-
name: "draw-residential",
|
|
1095
|
-
description: "\u751F\u6210\u519C\u6751\u6C11\u5C45\u5E73\u9762\u5E03\u7F6E\u56FE",
|
|
1096
|
-
arguments: [
|
|
1097
|
-
{ name: "width", description: "\u5EFA\u7B51\u5BBD\u5EA6 (mm)", required: true },
|
|
1098
|
-
{ name: "depth", description: "\u5EFA\u7B51\u6DF1\u5EA6 (mm)", required: true },
|
|
1099
|
-
{ name: "rooms", description: "\u623F\u95F4\u6570\u91CF", required: false }
|
|
1100
|
-
]
|
|
1101
|
-
},
|
|
1102
|
-
{
|
|
1103
|
-
name: "draw-floor-plan",
|
|
1104
|
-
description: "\u751F\u6210\u5EFA\u7B51\u697C\u5C42\u5E73\u9762\u56FE",
|
|
1105
|
-
arguments: [
|
|
1106
|
-
{ name: "floor", description: "\u697C\u5C42\u540D\u79F0", required: true },
|
|
1107
|
-
{ name: "scale", description: "\u56FE\u7EB8\u6BD4\u4F8B", required: false }
|
|
1108
|
-
]
|
|
1109
|
-
},
|
|
1110
1303
|
{
|
|
1111
1304
|
name: "analyze-drawing",
|
|
1112
1305
|
description: "\u5206\u6790\u5F53\u524D\u56FE\u7EB8\u7EDF\u8BA1\u4FE1\u606F",
|
|
@@ -1226,10 +1419,6 @@ async function listPrompts() {
|
|
|
1226
1419
|
}
|
|
1227
1420
|
async function getPrompt(name, arguments_ = {}) {
|
|
1228
1421
|
switch (name) {
|
|
1229
|
-
case "draw-residential":
|
|
1230
|
-
return generateResidentialPrompt(arguments_);
|
|
1231
|
-
case "draw-floor-plan":
|
|
1232
|
-
return generateFloorPlanPrompt(arguments_);
|
|
1233
1422
|
case "analyze-drawing":
|
|
1234
1423
|
return generateAnalyzePrompt();
|
|
1235
1424
|
case "batch-draw-lines":
|
|
@@ -1262,65 +1451,6 @@ async function getPrompt(name, arguments_ = {}) {
|
|
|
1262
1451
|
throw new Error(`Unknown prompt: ${name}`);
|
|
1263
1452
|
}
|
|
1264
1453
|
}
|
|
1265
|
-
async function generateResidentialPrompt(args) {
|
|
1266
|
-
const { width = 15e3, depth = 12e3, rooms = 6 } = args;
|
|
1267
|
-
const code = `(defun c:draw-residential (/ old-layer p)
|
|
1268
|
-
(setq old-layer (getvar "clayer"))
|
|
1269
|
-
(setvar "clayer" "0")
|
|
1270
|
-
(setq p (list 0 0))
|
|
1271
|
-
(command "_.rectangle" p (list ${width} ${depth}))
|
|
1272
|
-
${generateRoomLayout(width, depth, rooms)}
|
|
1273
|
-
(setvar "clayer" old-layer)
|
|
1274
|
-
(princ)
|
|
1275
|
-
)
|
|
1276
|
-
(c:draw-residential)`;
|
|
1277
|
-
return {
|
|
1278
|
-
messages: [{
|
|
1279
|
-
role: "user",
|
|
1280
|
-
content: {
|
|
1281
|
-
type: "text",
|
|
1282
|
-
text: `\u8BF7\u5728 CAD \u4E2D\u7ED8\u5236\u519C\u6751\u6C11\u5C45\u5E73\u9762\u56FE\uFF0C\u5C3A\u5BF8 ${width}x${depth}mm\uFF0C${rooms} \u4E2A\u623F\u95F4\u3002
|
|
1283
|
-
|
|
1284
|
-
\u751F\u6210\u7684 AutoLISP \u4EE3\u7801\uFF1A
|
|
1285
|
-
\`\`\`lisp
|
|
1286
|
-
${code}
|
|
1287
|
-
\`\`\`
|
|
1288
|
-
|
|
1289
|
-
\u76F4\u63A5\u6267\u884C\u6B64\u4EE3\u7801\u5373\u53EF\u751F\u6210\u56FE\u7EB8\u3002`
|
|
1290
|
-
}
|
|
1291
|
-
}]
|
|
1292
|
-
};
|
|
1293
|
-
}
|
|
1294
|
-
function generateRoomLayout(width, depth, rooms) {
|
|
1295
|
-
if (rooms === 6) {
|
|
1296
|
-
return `(command "_.line" (list 5000 0) (list 5000 ${depth}) "")
|
|
1297
|
-
(command "_.line" (list 0 4000) (list ${width} 4000) "")
|
|
1298
|
-
(command "_.text" "j" "c" "2500,2000" 800 0 "\u5BA2\u5385")
|
|
1299
|
-
(command "_.text" "j" "c" "7500,6000" 800 0 "\u9910\u5385")
|
|
1300
|
-
(command "_.text" "j" "c" "12500,2000" 800 0 "\u4E3B\u5367")`;
|
|
1301
|
-
}
|
|
1302
|
-
return `(command "_.text" "j" "c" (list (/ ${width} 2) (/ ${depth} 2)) 800 0 "\u623F\u95F4")`;
|
|
1303
|
-
}
|
|
1304
|
-
async function generateFloorPlanPrompt(args) {
|
|
1305
|
-
const { floor = "\u4E00\u5C42", scale = "1:100" } = args;
|
|
1306
|
-
return {
|
|
1307
|
-
messages: [{
|
|
1308
|
-
role: "user",
|
|
1309
|
-
content: {
|
|
1310
|
-
type: "text",
|
|
1311
|
-
text: `\u751F\u6210 ${floor} \u5E73\u9762\u56FE\uFF0C\u6BD4\u4F8B ${scale}\u3002
|
|
1312
|
-
|
|
1313
|
-
\u63D0\u793A\uFF1A
|
|
1314
|
-
1. \u4F7F\u7528 RECTANGLE \u547D\u4EE4\u7ED8\u5236\u5916\u5899
|
|
1315
|
-
2. \u4F7F\u7528 LINE \u547D\u4EE4\u7ED8\u5236\u5185\u90E8\u9694\u5899
|
|
1316
|
-
3. \u4F7F\u7528 TEXT \u547D\u4EE4\u6DFB\u52A0\u623F\u95F4\u6807\u6CE8
|
|
1317
|
-
4. \u4F7F\u7528 DIMLINEAR \u6216 DIMALIGNED \u6DFB\u52A0\u5C3A\u5BF8\u6807\u6CE8
|
|
1318
|
-
|
|
1319
|
-
\u9700\u8981\u6211\u6267\u884C\u54EA\u4E9B\u64CD\u4F5C\uFF1F`
|
|
1320
|
-
}
|
|
1321
|
-
}]
|
|
1322
|
-
};
|
|
1323
|
-
}
|
|
1324
1454
|
async function generateAnalyzePrompt() {
|
|
1325
1455
|
let entities = { total: 0, byType: {} };
|
|
1326
1456
|
let layers = [];
|
|
@@ -1368,10 +1498,14 @@ ${generateSuggestions(entities, layers)}`
|
|
|
1368
1498
|
}
|
|
1369
1499
|
function generateSuggestions(entities, layers) {
|
|
1370
1500
|
const suggestions = [];
|
|
1371
|
-
if (entities.total > 1e3)
|
|
1372
|
-
|
|
1373
|
-
if (
|
|
1374
|
-
|
|
1501
|
+
if (entities.total > 1e3)
|
|
1502
|
+
suggestions.push("- \u56FE\u7EB8\u5B9E\u4F53\u8F83\u591A\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u56FE\u5C42\u5206\u7C7B\u7BA1\u7406");
|
|
1503
|
+
if (layers.length > 20)
|
|
1504
|
+
suggestions.push("- \u56FE\u5C42\u8F83\u591A\uFF0C\u5EFA\u8BAE\u6E05\u7406\u672A\u4F7F\u7528\u7684\u56FE\u5C42");
|
|
1505
|
+
if (entities.byType.LINE && entities.byType.LINE > 500)
|
|
1506
|
+
suggestions.push("- \u7EBF\u6761\u8F83\u591A\uFF0C\u53EF\u8003\u8651\u4F7F\u7528 BLOCK \u51CF\u5C11\u5B9E\u4F53\u6570\u91CF");
|
|
1507
|
+
if (!entities.byType.DIMENSION)
|
|
1508
|
+
suggestions.push("- \u672A\u53D1\u73B0\u5C3A\u5BF8\u6807\u6CE8\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u6807\u6CE8");
|
|
1375
1509
|
return suggestions.length ? suggestions.join("\n") : "- \u56FE\u7EB8\u7ED3\u6784\u826F\u597D";
|
|
1376
1510
|
}
|
|
1377
1511
|
async function generateBatchLinesPrompt(args) {
|
|
@@ -2099,9 +2233,11 @@ var SseSession = class {
|
|
|
2099
2233
|
return lines.join("\n") + "\n\n";
|
|
2100
2234
|
}
|
|
2101
2235
|
_setupDrain() {
|
|
2102
|
-
if (typeof this.#res.on !== "function")
|
|
2236
|
+
if (typeof this.#res.on !== "function")
|
|
2237
|
+
return;
|
|
2103
2238
|
this.#drainHandler = () => {
|
|
2104
|
-
if (!this.#active)
|
|
2239
|
+
if (!this.#active)
|
|
2240
|
+
return;
|
|
2105
2241
|
if (this.#backpressureBuffer.length > 0) {
|
|
2106
2242
|
this._drainBuffer();
|
|
2107
2243
|
}
|
|
@@ -2123,7 +2259,8 @@ var SseSession = class {
|
|
|
2123
2259
|
}
|
|
2124
2260
|
}
|
|
2125
2261
|
_write(content) {
|
|
2126
|
-
if (!this.#active)
|
|
2262
|
+
if (!this.#active)
|
|
2263
|
+
return false;
|
|
2127
2264
|
try {
|
|
2128
2265
|
if (this.#backpressureBuffer.length > 0) {
|
|
2129
2266
|
this.#backpressureBuffer.push(content);
|
|
@@ -2172,8 +2309,8 @@ var SseSession = class {
|
|
|
2172
2309
|
sendMessage(data) {
|
|
2173
2310
|
return this.sendEvent(SSE_EVENTS.MESSAGE, data);
|
|
2174
2311
|
}
|
|
2175
|
-
sendEndpoint(
|
|
2176
|
-
return this.sendEvent(SSE_EVENTS.ENDPOINT,
|
|
2312
|
+
sendEndpoint(path6) {
|
|
2313
|
+
return this.sendEvent(SSE_EVENTS.ENDPOINT, path6);
|
|
2177
2314
|
}
|
|
2178
2315
|
sendError(code, message, id = null) {
|
|
2179
2316
|
return this.sendEvent(SSE_EVENTS.ERROR, { code, message }, id);
|
|
@@ -2339,9 +2476,9 @@ var SseSessionManager = class {
|
|
|
2339
2476
|
};
|
|
2340
2477
|
|
|
2341
2478
|
// src/atlisp-mcp.js
|
|
2342
|
-
var
|
|
2479
|
+
var __dirname3 = path5.dirname(fileURLToPath3(import.meta.url));
|
|
2343
2480
|
var require2 = createRequire(import.meta.url);
|
|
2344
|
-
var { version } = require2(
|
|
2481
|
+
var { version } = require2(path5.join(__dirname3, "..", "package.json"));
|
|
2345
2482
|
var isMcpScript = process.argv[1]?.includes("atlisp-mcp");
|
|
2346
2483
|
if (isMcpScript) {
|
|
2347
2484
|
const args = process.argv.slice(2);
|
|
@@ -2393,7 +2530,8 @@ var SERVER_CAPABILITIES = {
|
|
|
2393
2530
|
prompts: {}
|
|
2394
2531
|
};
|
|
2395
2532
|
var { port, host, transport, apiKey, rateLimitWindow, rateLimitMax } = config_default;
|
|
2396
|
-
if (apiKey)
|
|
2533
|
+
if (apiKey)
|
|
2534
|
+
log("API Key authentication enabled");
|
|
2397
2535
|
var mcpLimiter = rateLimit({
|
|
2398
2536
|
windowMs: rateLimitWindow,
|
|
2399
2537
|
max: rateLimitMax,
|
|
@@ -2441,9 +2579,11 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
2441
2579
|
init_atlisp: () => initAtlisp(),
|
|
2442
2580
|
get_function_usage: (a) => getFunctionUsage(a.name, a.package),
|
|
2443
2581
|
list_symbols: (a) => listSymbols(a.package),
|
|
2582
|
+
get_system_status: () => getSystemStatus(),
|
|
2444
2583
|
import_funlib: async (a) => {
|
|
2445
2584
|
const data = await loadAtlibFunctionLib();
|
|
2446
|
-
if (!data)
|
|
2585
|
+
if (!data)
|
|
2586
|
+
return { content: [{ type: "text", text: "\u52A0\u8F7D\u51FD\u6570\u5E93\u5931\u8D25" }], isError: true };
|
|
2447
2587
|
if (a.format === "list") {
|
|
2448
2588
|
const items = Object.values(data.all_functions || {}).map((f) => `${f.name}: ${f.description || ""}`);
|
|
2449
2589
|
return { content: [{ type: "text", text: items.join("\n") }] };
|
|
@@ -2601,11 +2741,17 @@ var tools = [
|
|
|
2601
2741
|
format: { type: "string", enum: ["json", "list"], description: "\u8FD4\u56DE\u683C\u5F0F\uFF1Ajson\uFF08\u5B8C\u6574JSON\uFF09\u6216 list\uFF08\u51FD\u6570\u540D:\u63CF\u8FF0 \u5217\u8868\uFF09\uFF0C\u9ED8\u8BA4 json" }
|
|
2602
2742
|
}
|
|
2603
2743
|
}
|
|
2744
|
+
},
|
|
2745
|
+
{
|
|
2746
|
+
name: "get_system_status",
|
|
2747
|
+
description: "\u83B7\u53D6\u5B8C\u6574\u7CFB\u7EDF\u8BCA\u65AD\u4FE1\u606F\uFF1AMCP \u72B6\u6001\u3001CAD \u8FDE\u63A5\u3001Lisp \u6267\u884C\u3001\u5305\u5217\u8868",
|
|
2748
|
+
inputSchema: { type: "object", properties: {} }
|
|
2604
2749
|
}
|
|
2605
2750
|
];
|
|
2606
2751
|
async function handleToolCall(name, args) {
|
|
2607
2752
|
const handler = TOOL_HANDLERS[name];
|
|
2608
|
-
if (!handler)
|
|
2753
|
+
if (!handler)
|
|
2754
|
+
return { content: [{ type: "text", text: `\u672A\u77E5\u5DE5\u5177: ${name}` }], isError: true };
|
|
2609
2755
|
try {
|
|
2610
2756
|
const result = await handler(args || {});
|
|
2611
2757
|
notifyResourceChanges(name);
|
|
@@ -2617,8 +2763,8 @@ async function handleToolCall(name, args) {
|
|
|
2617
2763
|
}
|
|
2618
2764
|
function notifyResourceChanges(toolName) {
|
|
2619
2765
|
const resourceMap = {
|
|
2620
|
-
connect_cad: ["atlisp://cad/info", "atlisp://
|
|
2621
|
-
new_document: ["atlisp://dwg/name", "atlisp://dwg/path", "atlisp://cad/layers", "atlisp://
|
|
2766
|
+
connect_cad: ["atlisp://cad/info", "atlisp://dwg/layers", "atlisp://dwg/name", "atlisp://dwg/path", "atlisp://cad/dwgs", "atlisp://packages"],
|
|
2767
|
+
new_document: ["atlisp://dwg/name", "atlisp://dwg/path", "atlisp://cad/dwgs", "atlisp://dwg/layers", "atlisp://dwg/entities"],
|
|
2622
2768
|
install_package: ["atlisp://packages"],
|
|
2623
2769
|
install_atlisp: ["atlisp://packages", "atlisp://cad/info"],
|
|
2624
2770
|
init_atlisp: ["atlisp://packages", "atlisp://cad/info"]
|
|
@@ -2728,7 +2874,8 @@ async function startServer() {
|
|
|
2728
2874
|
const JSON_CONTENT_TYPES = ["application/json", "application/json-rpc", "application/vnd.api+json"];
|
|
2729
2875
|
app.use(async (req, res, next) => {
|
|
2730
2876
|
const ct = (req.headers["content-type"] || "").toLowerCase();
|
|
2731
|
-
if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
|
|
2877
|
+
if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
|
|
2878
|
+
return next();
|
|
2732
2879
|
try {
|
|
2733
2880
|
const buf = await rawBody(req, { limit: "10mb" });
|
|
2734
2881
|
const m = ct.match(/charset\s*=\s*([^\s;]+)/i);
|
|
@@ -2749,9 +2896,11 @@ async function startServer() {
|
|
|
2749
2896
|
const PUBLIC_PATHS = ["/health"];
|
|
2750
2897
|
if (apiKey) {
|
|
2751
2898
|
app.use((req, res, next) => {
|
|
2752
|
-
if (PUBLIC_PATHS.includes(req.path))
|
|
2899
|
+
if (PUBLIC_PATHS.includes(req.path))
|
|
2900
|
+
return next();
|
|
2753
2901
|
const auth = req.get("Authorization");
|
|
2754
|
-
if (auth === `Bearer ${apiKey}`)
|
|
2902
|
+
if (auth === `Bearer ${apiKey}`)
|
|
2903
|
+
return next();
|
|
2755
2904
|
res.status(401).json({ error: "Unauthorized" });
|
|
2756
2905
|
});
|
|
2757
2906
|
}
|
|
@@ -2766,7 +2915,8 @@ async function startServer() {
|
|
|
2766
2915
|
res.setHeader("Access-Control-Expose-Headers", "mcp-session-id, content-type, x-accel-buffering");
|
|
2767
2916
|
res.setHeader("Access-Control-Max-Age", "86400");
|
|
2768
2917
|
res.setHeader("Vary", "Accept");
|
|
2769
|
-
if (req.method === "OPTIONS")
|
|
2918
|
+
if (req.method === "OPTIONS")
|
|
2919
|
+
return res.status(204).end();
|
|
2770
2920
|
next();
|
|
2771
2921
|
});
|
|
2772
2922
|
}
|