@atlisp/mcp 1.3.4 → 1.3.7

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.
@@ -34,8 +34,7 @@ var SessionTransport = class {
34
34
  this._started = true;
35
35
  }
36
36
  async send(message) {
37
- if (this._closed)
38
- return;
37
+ if (this._closed) return;
39
38
  if (this._pendingRequest) {
40
39
  const { resolve, reject, timeout } = this._pendingRequest;
41
40
  clearTimeout(timeout);
@@ -44,8 +43,7 @@ var SessionTransport = class {
44
43
  }
45
44
  }
46
45
  async close() {
47
- if (this._closed)
48
- return;
46
+ if (this._closed) return;
49
47
  this._closed = true;
50
48
  if (this._pendingRequest) {
51
49
  const { reject, timeout } = this._pendingRequest;
@@ -212,8 +210,7 @@ function setupStdoutHandler(w) {
212
210
  const lines = buffer.split("\n");
213
211
  buffer = lines.pop() || "";
214
212
  for (const line of lines) {
215
- if (!line.trim())
216
- continue;
213
+ if (!line.trim()) continue;
217
214
  try {
218
215
  const result = JSON.parse(line);
219
216
  const rid = result.requestId;
@@ -238,8 +235,7 @@ function setupStdoutHandler(w) {
238
235
  }
239
236
  function getWorker() {
240
237
  if (!worker || !worker.connected) {
241
- if (worker)
242
- worker.kill();
238
+ if (worker) worker.kill();
243
239
  worker = spawn("node", [workerPath], {
244
240
  stdio: ["pipe", "pipe", "pipe"]
245
241
  });
@@ -248,8 +244,7 @@ function getWorker() {
248
244
  const w = worker;
249
245
  w.on("exit", (code) => {
250
246
  console.error("worker exited:", code);
251
- if (w !== worker)
252
- return;
247
+ if (w !== worker) return;
253
248
  w.connected = false;
254
249
  for (const [id, { reject, timeout }] of pendingRequests) {
255
250
  clearTimeout(timeout);
@@ -268,8 +263,7 @@ function getWorker() {
268
263
  return worker;
269
264
  }
270
265
  function startHeartbeat() {
271
- if (heartbeatTimer)
272
- clearInterval(heartbeatTimer);
266
+ if (heartbeatTimer) clearInterval(heartbeatTimer);
273
267
  heartbeatTimer = setInterval(async () => {
274
268
  try {
275
269
  const result = await sendMessage({ type: "ping" });
@@ -314,8 +308,7 @@ var CadConnection = class {
314
308
  return process.platform === "win32";
315
309
  }
316
310
  async connect() {
317
- if (!this.isAvailable())
318
- return false;
311
+ if (!this.isAvailable()) return false;
319
312
  try {
320
313
  const result = await sendMessage({ type: "connect" });
321
314
  if (result && result.success) {
@@ -331,16 +324,13 @@ var CadConnection = class {
331
324
  return false;
332
325
  }
333
326
  async sendCommand(code) {
334
- if (!this.connected)
335
- throw new Error("\u672A\u8FDE\u63A5 CAD");
327
+ if (!this.connected) throw new Error("\u672A\u8FDE\u63A5 CAD");
336
328
  const result = await sendMessage({ type: "send", code, platform: _platform });
337
- if (result.success)
338
- return true;
329
+ if (result.success) return true;
339
330
  throw new Error(result.error || "\u53D1\u9001\u5931\u8D25");
340
331
  }
341
332
  async sendCommandWithResult(code, encoding = null) {
342
- if (!this.connected)
343
- throw new Error("\u672A\u8FDE\u63A5 CAD");
333
+ if (!this.connected) throw new Error("\u672A\u8FDE\u63A5 CAD");
344
334
  const result = await sendMessage({ type: "sendResult", code, platform: _platform, encoding: encoding || "" });
345
335
  if (result.success) {
346
336
  return result.result || "";
@@ -354,8 +344,7 @@ var CadConnection = class {
354
344
  return this.product;
355
345
  }
356
346
  async isBusy() {
357
- if (!this.connected)
358
- return false;
347
+ if (!this.connected) return false;
359
348
  try {
360
349
  const result = await sendMessage({ type: "isBusy", platform: _platform });
361
350
  return result && result.isBusy;
@@ -364,8 +353,7 @@ var CadConnection = class {
364
353
  }
365
354
  }
366
355
  async hasDoc() {
367
- if (!this.connected)
368
- return { hasDoc: false, docCount: 0 };
356
+ if (!this.connected) return { hasDoc: false, docCount: 0 };
369
357
  try {
370
358
  const result = await sendMessage({ type: "hasdoc", platform: _platform });
371
359
  return result || { hasDoc: false, docCount: 0 };
@@ -374,8 +362,7 @@ var CadConnection = class {
374
362
  }
375
363
  }
376
364
  async newDoc() {
377
- if (!this.connected)
378
- throw new Error("\u672A\u8FDE\u63A5 CAD");
365
+ if (!this.connected) throw new Error("\u672A\u8FDE\u63A5 CAD");
379
366
  try {
380
367
  const result = await sendMessage({ type: "newdoc", platform: _platform });
381
368
  return result && result.success;
@@ -384,8 +371,7 @@ var CadConnection = class {
384
371
  }
385
372
  }
386
373
  async bringToFront() {
387
- if (!this.connected)
388
- throw new Error("\u672A\u8FDE\u63A5 CAD");
374
+ if (!this.connected) throw new Error("\u672A\u8FDE\u63A5 CAD");
389
375
  try {
390
376
  const result = await sendMessage({ type: "bringToFront", platform: _platform });
391
377
  return result && result.success;
@@ -394,8 +380,7 @@ var CadConnection = class {
394
380
  }
395
381
  }
396
382
  async getInfo() {
397
- if (!this.connected)
398
- return "CAD \u672A\u8FDE\u63A5";
383
+ if (!this.connected) return "CAD \u672A\u8FDE\u63A5";
399
384
  return `Platform: ${this.product}, Version: ${this.version}, Status: Connected`;
400
385
  }
401
386
  async disconnect() {
@@ -469,16 +454,18 @@ async function evalLisp(code, withResult = false, encoding = null) {
469
454
  if (!cad.connected) {
470
455
  return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
471
456
  }
457
+ const trimmed = (code || "").trim();
458
+ if (!trimmed) return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
472
459
  try {
473
460
  if (withResult) {
474
- const result = await cad.sendCommandWithResult(code, encoding);
461
+ const result = await cad.sendCommandWithResult(trimmed, encoding);
475
462
  if (result !== null) {
476
463
  return { content: [{ type: "text", text: result }] };
477
464
  }
478
465
  return { content: [{ type: "text", text: "\u6267\u884C\u5931\u8D25\u6216\u65E0\u8FD4\u56DE\u503C" }], isError: true };
479
466
  } else {
480
- await cad.sendCommand(code + "\n");
481
- return { content: [{ type: "text", text: `\u5DF2\u53D1\u9001\u547D\u4EE4: ${code}` }] };
467
+ await cad.sendCommand(trimmed + "\n");
468
+ return { content: [{ type: "text", text: `\u5DF2\u53D1\u9001\u547D\u4EE4` }] };
482
469
  }
483
470
  } catch (e) {
484
471
  return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
@@ -488,23 +475,22 @@ async function getCadInfo() {
488
475
  if (!cad.connected) {
489
476
  await cad.connect();
490
477
  }
491
- if (!cad.connected)
492
- return { content: [{ type: "text", text: "CAD \u672A\u8FDE\u63A5" }] };
478
+ if (!cad.connected) return { content: [{ type: "text", text: "CAD \u672A\u8FDE\u63A5" }] };
493
479
  const info = await cad.getInfo();
494
480
  return { content: [{ type: "text", text: info }] };
495
481
  }
496
482
  async function atCommand(command) {
497
- if (!cad.connected)
498
- return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
499
- await cad.sendCommand(command + "\n");
500
- return { content: [{ type: "text", text: `\u5DF2\u53D1\u9001\u547D\u4EE4: ${command}` }] };
483
+ if (!cad.connected) return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
484
+ const trimmed = (command || "").trim();
485
+ if (!trimmed) return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
486
+ await cad.sendCommand(trimmed + "\n");
487
+ return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001\u547D\u4EE4" }] };
501
488
  }
502
489
  async function newDocument() {
503
490
  if (!cad.connected) {
504
491
  await cad.connect();
505
492
  }
506
- if (!cad.connected)
507
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
493
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
508
494
  const result = await cad.newDoc();
509
495
  if (result) {
510
496
  return { content: [{ type: "text", text: "\u5DF2\u5728 CAD \u4E2D\u65B0\u5EFA\u7A7A\u767D\u6587\u6863" }] };
@@ -515,8 +501,7 @@ async function bringToFront() {
515
501
  if (!cad.connected) {
516
502
  await cad.connect();
517
503
  }
518
- if (!cad.connected)
519
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
504
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
520
505
  const result = await cad.bringToFront();
521
506
  if (result) {
522
507
  return { content: [{ type: "text", text: "\u5DF2\u5C06 CAD \u7A97\u53E3\u5207\u6362\u5230\u524D\u53F0" }] };
@@ -527,8 +512,7 @@ async function installAtlisp() {
527
512
  if (!cad.connected) {
528
513
  await cad.connect();
529
514
  }
530
- if (!cad.connected)
531
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
515
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
532
516
  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))))`;
533
517
  await cad.sendCommand(installCode + "\n");
534
518
  return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001 @lisp \u5B89\u88C5\u4EE3\u7801\u5230 CAD" }] };
@@ -537,12 +521,10 @@ async function listFunctionsInCad() {
537
521
  if (!cad.connected) {
538
522
  await cad.connect();
539
523
  }
540
- if (!cad.connected)
541
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
524
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
542
525
  try {
543
526
  const result = await cad.sendCommandWithResult("(atoms-family 0)", null);
544
- if (result)
545
- return { content: [{ type: "text", text: result }] };
527
+ if (result) return { content: [{ type: "text", text: result }] };
546
528
  return { content: [{ type: "text", text: "CAD \u51FD\u6570\u5217\u8868\u4E3A\u7A7A" }] };
547
529
  } catch (e) {
548
530
  return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
@@ -552,8 +534,7 @@ async function initAtlisp() {
552
534
  if (!cad.connected) {
553
535
  await cad.connect();
554
536
  }
555
- if (!cad.connected)
556
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
537
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
557
538
  const code = `(if (null @::load-module)
558
539
  (progn
559
540
  (vl-load-com)
@@ -593,13 +574,10 @@ async function fetchPackages() {
593
574
  return null;
594
575
  }
595
576
  async function listPackages() {
596
- if (!cad.connected)
597
- await cad.connect();
598
- if (!cad.connected)
599
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
577
+ if (!cad.connected) await cad.connect();
578
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
600
579
  const result = await cad.sendCommandWithResult("(@::package-list-in-local)");
601
- if (result && result !== "nil")
602
- return { content: [{ type: "text", text: result }] };
580
+ if (result && result !== "nil") return { content: [{ type: "text", text: result }] };
603
581
  const packages = MOCK_PACKAGES.map((p) => `${p.name} v${p.version} - ${p.description}`);
604
582
  return { content: [{ type: "text", text: `\u5DF2\u5B89\u88C5\u7684 @lisp \u5305:
605
583
  ${packages.join("\n")}` }] };
@@ -616,12 +594,10 @@ async function searchPackages(query) {
616
594
  for (const p of items) {
617
595
  const name = (p.name || "").toLowerCase();
618
596
  const desc = (p.description || "").toLowerCase();
619
- if (name.includes(q) || desc.includes(q))
620
- results.push(p);
597
+ if (name.includes(q) || desc.includes(q)) results.push(p);
621
598
  }
622
599
  } else {
623
- for (const p of items)
624
- results.push(p);
600
+ for (const p of items) results.push(p);
625
601
  }
626
602
  if (results.length === 0) {
627
603
  return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5305\u542B "${query}" \u7684\u5305` }] };
@@ -663,8 +639,7 @@ async function getFunctionUsage(funcName, packageName) {
663
639
  const data = await response.json();
664
640
  const funcs = Object.values(data.all_functions || {});
665
641
  const func = funcs.find((f2) => f2.name === funcName || f2.name === `${packageName}:${funcName}`);
666
- if (func)
667
- results.push(func);
642
+ if (func) results.push(func);
668
643
  }
669
644
  } catch (e) {
670
645
  log(`function-handlers fetch error: ${e.message}`);
@@ -675,8 +650,7 @@ async function getFunctionUsage(funcName, packageName) {
675
650
  const raw = await fs2.readFile(path3.join(FUNCTIONS_DIR, file), "utf-8");
676
651
  const data = JSON.parse(raw);
677
652
  const func = data.functions?.find((f2) => f2.name === funcName);
678
- if (func)
679
- results.push(func);
653
+ if (func) results.push(func);
680
654
  }
681
655
  }
682
656
  if (results.length === 0) {
@@ -757,14 +731,11 @@ function setCache(key, data) {
757
731
  resourceCache.set(key, { data, timestamp: Date.now() });
758
732
  }
759
733
  function parseLispList(str) {
760
- if (!str || typeof str !== "string")
761
- return null;
734
+ if (!str || typeof str !== "string") return null;
762
735
  const trimmed = str.trim();
763
- if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
764
- return null;
736
+ if (!trimmed.startsWith("(") || !trimmed.endsWith(")")) return null;
765
737
  const content = trimmed.slice(1, -1).trim();
766
- if (!content)
767
- return [];
738
+ if (!content) return [];
768
739
  const result = [];
769
740
  let depth = 0;
770
741
  let current = "";
@@ -806,21 +777,15 @@ function parseLispList(str) {
806
777
  }
807
778
  current += ch;
808
779
  }
809
- if (current.trim())
810
- result.push(current.trim());
780
+ if (current.trim()) result.push(current.trim());
811
781
  return result.map((item) => {
812
782
  const t = item.trim();
813
- if (t === "nil")
814
- return null;
815
- if (t === "t")
816
- return true;
817
- if (t === "T")
818
- return true;
783
+ if (t === "nil") return null;
784
+ if (t === "t") return true;
785
+ if (t === "T") return true;
819
786
  const num = Number(t);
820
- if (!isNaN(num) && t !== "")
821
- return num;
822
- if (t.startsWith('"') && t.endsWith('"'))
823
- return t.slice(1, -1);
787
+ if (!isNaN(num) && t !== "") return num;
788
+ if (t.startsWith('"') && t.endsWith('"')) return t.slice(1, -1);
824
789
  return t;
825
790
  });
826
791
  }
@@ -835,16 +800,14 @@ var RESOURCES = [
835
800
  ];
836
801
  function parseQuery(uri) {
837
802
  const qIdx = uri.indexOf("?");
838
- if (qIdx === -1)
839
- return { base: uri, params: {} };
803
+ if (qIdx === -1) return { base: uri, params: {} };
840
804
  const base = uri.substring(0, qIdx);
841
805
  const params = {};
842
806
  uri.substring(qIdx + 1).split("&").forEach((p) => {
843
807
  const eqIdx = p.indexOf("=");
844
808
  const k = eqIdx === -1 ? p : p.substring(0, eqIdx);
845
809
  const v = eqIdx === -1 ? "" : p.substring(eqIdx + 1);
846
- if (k)
847
- params[k] = decodeURIComponent(v);
810
+ if (k) params[k] = decodeURIComponent(v);
848
811
  });
849
812
  return { base, params };
850
813
  }
@@ -880,8 +843,7 @@ async function readResource(uri) {
880
843
  }
881
844
  async function getCadInfo2() {
882
845
  const cached = getCached("cad:info");
883
- if (cached)
884
- return cached;
846
+ if (cached) return cached;
885
847
  if (!cad.connected) {
886
848
  await cad.connect();
887
849
  }
@@ -908,12 +870,9 @@ async function getCadInfo2() {
908
870
  async function getLayers(filterName = null) {
909
871
  const cacheKey = filterName ? `layers:${filterName}` : "layers:all";
910
872
  const cached = getCached(cacheKey);
911
- if (cached)
912
- return cached;
913
- if (!cad.connected)
914
- await cad.connect();
915
- if (!cad.connected)
916
- return [];
873
+ if (cached) return cached;
874
+ if (!cad.connected) await cad.connect();
875
+ if (!cad.connected) return [];
917
876
  try {
918
877
  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))`;
919
878
  const result = await cad.sendCommandWithResult(code);
@@ -960,10 +919,8 @@ async function getLayers(filterName = null) {
960
919
  async function getEntities(filterType = null) {
961
920
  const cacheKey = filterType ? `entities:${filterType}` : "entities:all";
962
921
  const cached = getCached(cacheKey);
963
- if (cached)
964
- return cached;
965
- if (!cad.connected)
966
- await cad.connect();
922
+ if (cached) return cached;
923
+ if (!cad.connected) await cad.connect();
967
924
  if (!cad.connected) {
968
925
  const result = { total: 0, byType: {} };
969
926
  setCache(cacheKey, result);
@@ -1017,10 +974,8 @@ async function getEntities(filterType = null) {
1017
974
  }
1018
975
  }
1019
976
  async function getDwgName() {
1020
- if (!cad.connected)
1021
- await cad.connect();
1022
- if (!cad.connected)
1023
- return { name: null };
977
+ if (!cad.connected) await cad.connect();
978
+ if (!cad.connected) return { name: null };
1024
979
  try {
1025
980
  const code = `(vl-princ-to-string (getvar "dwgname"))`;
1026
981
  const name = await cad.sendCommandWithResult(code);
@@ -1030,10 +985,8 @@ async function getDwgName() {
1030
985
  }
1031
986
  }
1032
987
  async function getDwgPath() {
1033
- if (!cad.connected)
1034
- await cad.connect();
1035
- if (!cad.connected)
1036
- return { path: null, name: null };
988
+ if (!cad.connected) await cad.connect();
989
+ if (!cad.connected) return { path: null, name: null };
1037
990
  try {
1038
991
  const code = `(progn
1039
992
  (setq prefix (vl-princ-to-string (getvar "dwgprefix")))
@@ -1051,8 +1004,7 @@ async function getDwgPath() {
1051
1004
  }
1052
1005
  if (!parsed) {
1053
1006
  const listResult = parseLispList(result);
1054
- if (listResult && listResult.length >= 2)
1055
- parsed = listResult;
1007
+ if (listResult && listResult.length >= 2) parsed = listResult;
1056
1008
  }
1057
1009
  if (parsed && Array.isArray(parsed) && parsed.length >= 2) {
1058
1010
  return { path: String(parsed[0]), name: String(parsed[1]) };
@@ -1127,6 +1079,92 @@ var PROMPTS = [
1127
1079
  arguments: [
1128
1080
  { name: "format", description: "\u5BFC\u51FA\u683C\u5F0F (json/list)", required: false }
1129
1081
  ]
1082
+ },
1083
+ {
1084
+ name: "manage-layers",
1085
+ description: "\u56FE\u5C42\u7BA1\u7406\uFF1A\u521B\u5EFA\u3001\u51BB\u7ED3\u3001\u9501\u5B9A\u3001\u5220\u9664\u56FE\u5C42",
1086
+ arguments: [
1087
+ { name: "action", description: "\u64CD\u4F5C\u7C7B\u578B (list/freeze/lock/off/make/delete)", required: true },
1088
+ { name: "layers", description: "\u56FE\u5C42\u540D\uFF0C\u591A\u4E2A\u7528\u9017\u53F7\u5206\u9694", required: false },
1089
+ { name: "color", description: '\u56FE\u5C42\u989C\u8272 (ACI\u53F7\u6216RGB\u5982 "1,2,3")', required: false }
1090
+ ]
1091
+ },
1092
+ {
1093
+ name: "manage-blocks",
1094
+ description: "\u5757\u64CD\u4F5C\uFF1A\u63D2\u5165\u5757\u3001\u5217\u51FA\u5757\u3001\u83B7\u53D6/\u8BBE\u7F6E\u5C5E\u6027",
1095
+ arguments: [
1096
+ { name: "action", description: "\u64CD\u4F5C\u7C7B\u578B (list/insert/attributes/dynprops)", required: true },
1097
+ { name: "blockName", description: "\u5757\u540D", required: false },
1098
+ { name: "insertPoint", description: '\u63D2\u5165\u70B9 "x,y"', required: false },
1099
+ { name: "scale", description: "\u7F29\u653E\u6BD4\u4F8B", required: false }
1100
+ ]
1101
+ },
1102
+ {
1103
+ name: "curve-analysis",
1104
+ description: "\u66F2\u7EBF\u5206\u6790\uFF1A\u4EA4\u70B9\u3001\u6700\u8FD1\u70B9\u3001\u5B50\u6BB5\u3001\u7F13\u51B2\u533A",
1105
+ arguments: [
1106
+ { name: "action", description: "\u64CD\u4F5C (inters/subsegments/closestpoint/join)", required: true },
1107
+ { name: "distance", description: "\u8FDE\u63A5\u5BB9\u5DEE/\u504F\u79FB\u8DDD\u79BB", required: false }
1108
+ ]
1109
+ },
1110
+ {
1111
+ name: "geometry-calc",
1112
+ description: "\u51E0\u4F55\u8BA1\u7B97\uFF1A\u51F8\u5305\u3001\u70B9\u5230\u7EBF\u8DDD\u79BB\u3001\u9762\u5185\u6D4B\u8BD5\u3001\u53D8\u6362",
1113
+ arguments: [
1114
+ { name: "action", description: "\u64CD\u4F5C (convexhull/dist-point-line/in-curve-p/transform/centroid)", required: true },
1115
+ { name: "points", description: '\u70B9\u96C6 "x1,y1;x2,y2;..."', required: false }
1116
+ ]
1117
+ },
1118
+ {
1119
+ name: "text-process",
1120
+ description: "\u6587\u672C\u5904\u7406\uFF1AMTEXT\u89E3\u6790\u3001Markdown\u8F6CMTEXT\u3001\u53BB\u683C\u5F0F",
1121
+ arguments: [
1122
+ { name: "action", description: "\u64CD\u4F5C (parse-mtext/remove-fmt/from-markdown/mtext2text)", required: true },
1123
+ { name: "markdown", description: "Markdown\u6587\u672C\uFF08from-markdown\u64CD\u4F5C\u65F6\u7528\uFF09", required: false }
1124
+ ]
1125
+ },
1126
+ {
1127
+ name: "pickset-filter",
1128
+ description: "\u9009\u62E9\u96C6\u64CD\u4F5C\uFF1A\u8FC7\u6EE4\u3001\u8F6C\u6362\u3001\u6279\u91CF\u64CD\u4F5C",
1129
+ arguments: [
1130
+ { name: "action", description: "\u64CD\u4F5C (by-layer/by-type/by-box/erase/zoom)", required: true },
1131
+ { name: "dxfType", description: 'DXF\u7C7B\u578B "LINE, CIRCLE, LWPOLYLINE, INSERT, TEXT"', required: false },
1132
+ { name: "layerName", description: "\u56FE\u5C42\u540D", required: false }
1133
+ ]
1134
+ },
1135
+ {
1136
+ name: "color-convert",
1137
+ description: "\u989C\u8272\u8F6C\u6362\uFF1AACI/RGB/TrueColor/CSS\u4E92\u8F6C",
1138
+ arguments: [
1139
+ { name: "action", description: "\u64CD\u4F5C (aci2rgb/rgb2css/truecolor2rgb/rgb2truecolor)", required: true },
1140
+ { name: "value", description: "\u989C\u8272\u503C", required: true }
1141
+ ]
1142
+ },
1143
+ {
1144
+ name: "json-exchange",
1145
+ description: "JSON\u6570\u636E\u4EA4\u6362\uFF1A\u4ECE\u5B57\u7B26\u4E32\u89E3\u6790JSON alist\uFF0C\u4ECEalist\u751F\u6210JSON",
1146
+ arguments: [
1147
+ { name: "action", description: "\u64CD\u4F5C (encode/decode)", required: true },
1148
+ { name: "data", description: "JSON\u5B57\u7B26\u4E32\u6216Lisp alist\u6587\u672C", required: true }
1149
+ ]
1150
+ },
1151
+ {
1152
+ name: "excel-report",
1153
+ description: "Excel\u62A5\u8868\uFF1A\u5BFC\u51FACAD\u5B9E\u4F53\u6570\u636E\u5230Excel",
1154
+ arguments: [
1155
+ { name: "visible", description: "\u662F\u5426\u663E\u793AExcel\u7A97\u53E3 (true/false)", required: false },
1156
+ { name: "savePath", description: "\u4FDD\u5B58\u8DEF\u5F84\uFF0C\u4E0D\u586B\u5219\u4E0D\u4FDD\u5B58", required: false }
1157
+ ]
1158
+ },
1159
+ {
1160
+ name: "string-process",
1161
+ description: "\u5B57\u7B26\u4E32\u5904\u7406\uFF1A\u683C\u5F0F\u5316\u3001\u62C6\u5206\u3001\u66FF\u6362\u3001\u6B63\u5219",
1162
+ arguments: [
1163
+ { name: "action", description: "\u64CD\u4F5C (format/split/subst-all/regexp/trim/number2chinese)", required: true },
1164
+ { name: "input", description: "\u8F93\u5165\u5B57\u7B26\u4E32", required: true },
1165
+ { name: "arg1", description: "\u53C2\u65701\uFF08\u683C\u5F0F\u53C2\u6570/\u5206\u9694\u7B26/\u65E7\u4E32\uFF09", required: false },
1166
+ { name: "arg2", description: "\u53C2\u65702\uFF08\u65B0\u4E32/\u6B63\u5219\u6A21\u5F0F\uFF09", required: false }
1167
+ ]
1130
1168
  }
1131
1169
  ];
1132
1170
  async function listPrompts() {
@@ -1146,6 +1184,26 @@ async function getPrompt(name, arguments_ = {}) {
1146
1184
  return generateDimensionPrompt(arguments_);
1147
1185
  case "export-entities":
1148
1186
  return generateExportPrompt(arguments_);
1187
+ case "manage-layers":
1188
+ return generateManageLayersPrompt(arguments_);
1189
+ case "manage-blocks":
1190
+ return generateManageBlocksPrompt(arguments_);
1191
+ case "curve-analysis":
1192
+ return generateCurveAnalysisPrompt(arguments_);
1193
+ case "geometry-calc":
1194
+ return generateGeometryCalcPrompt(arguments_);
1195
+ case "text-process":
1196
+ return generateTextProcessPrompt(arguments_);
1197
+ case "pickset-filter":
1198
+ return generatePicksetFilterPrompt(arguments_);
1199
+ case "color-convert":
1200
+ return generateColorConvertPrompt(arguments_);
1201
+ case "json-exchange":
1202
+ return generateJsonExchangePrompt(arguments_);
1203
+ case "excel-report":
1204
+ return generateExcelReportPrompt(arguments_);
1205
+ case "string-process":
1206
+ return generateStringProcessPrompt(arguments_);
1149
1207
  default:
1150
1208
  throw new Error(`Unknown prompt: ${name}`);
1151
1209
  }
@@ -1256,14 +1314,10 @@ ${generateSuggestions(entities, layers)}`
1256
1314
  }
1257
1315
  function generateSuggestions(entities, layers) {
1258
1316
  const suggestions = [];
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");
1317
+ if (entities.total > 1e3) suggestions.push("- \u56FE\u7EB8\u5B9E\u4F53\u8F83\u591A\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u56FE\u5C42\u5206\u7C7B\u7BA1\u7406");
1318
+ if (layers.length > 20) suggestions.push("- \u56FE\u5C42\u8F83\u591A\uFF0C\u5EFA\u8BAE\u6E05\u7406\u672A\u4F7F\u7528\u7684\u56FE\u5C42");
1319
+ if (entities.byType.LINE && entities.byType.LINE > 500) suggestions.push("- \u7EBF\u6761\u8F83\u591A\uFF0C\u53EF\u8003\u8651\u4F7F\u7528 BLOCK \u51CF\u5C11\u5B9E\u4F53\u6570\u91CF");
1320
+ if (!entities.byType.DIMENSION) suggestions.push("- \u672A\u53D1\u73B0\u5C3A\u5BF8\u6807\u6CE8\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u6807\u6CE8");
1267
1321
  return suggestions.length ? suggestions.join("\n") : "- \u56FE\u7EB8\u7ED3\u6784\u826F\u597D";
1268
1322
  }
1269
1323
  async function generateBatchLinesPrompt(args) {
@@ -1367,6 +1421,418 @@ ${code}
1367
1421
  }]
1368
1422
  };
1369
1423
  }
1424
+ async function generateManageLayersPrompt(args) {
1425
+ const { action = "list", layers = "", color = "" } = args;
1426
+ const layerList = layers ? layers.split(/[,, ]+/) : [];
1427
+ const codeMap = {
1428
+ list: `(layer:list)`,
1429
+ make: `(layer:make "${layerList[0] || "NEW-LAYER"}" ${color || "7"} "Continuous" 0)`,
1430
+ freeze: `(mapcar (function (lambda (x) (layer:freeze x 1))) '${JSON.stringify(layerList.length ? layerList : ["0"])})`,
1431
+ lock: `(mapcar (function (lambda (x) (layer:lock x 1))) '${JSON.stringify(layerList.length ? layerList : ["0"])})`,
1432
+ off: `(mapcar (function (lambda (x) (layer:off x))) '${JSON.stringify(layerList.length ? layerList : ["0"])})`,
1433
+ delete: `(mapcar (function (lambda (x) (layer:delete x))) '${JSON.stringify(layerList.length ? layerList : ["0"]).replace(/"/g, '"')})`
1434
+ };
1435
+ const code = codeMap[action] || codeMap.list;
1436
+ const descMap = {
1437
+ list: "\u5217\u51FA\u6240\u6709\u56FE\u5C42",
1438
+ make: `\u521B\u5EFA\u56FE\u5C42 ${layerList[0] || "NEW-LAYER"}\uFF0C\u989C\u8272 ${color || "7"}`,
1439
+ freeze: `\u51BB\u7ED3\u56FE\u5C42: ${layerList.join(", ") || "\u672A\u6307\u5B9A"}`,
1440
+ lock: `\u9501\u5B9A\u56FE\u5C42: ${layerList.join(", ") || "\u672A\u6307\u5B9A"}`,
1441
+ off: `\u5173\u95ED\u56FE\u5C42: ${layerList.join(", ") || "\u672A\u6307\u5B9A"}`,
1442
+ delete: `\u5220\u9664\u56FE\u5C42: ${layerList.join(", ") || "\u672A\u6307\u5B9A"}`
1443
+ };
1444
+ return {
1445
+ messages: [{
1446
+ role: "user",
1447
+ content: {
1448
+ type: "text",
1449
+ text: `${descMap[action] || descMap.list}
1450
+
1451
+ \`\`\`lisp
1452
+ ${code}
1453
+ \`\`\`
1454
+
1455
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1456
+ }
1457
+ }]
1458
+ };
1459
+ }
1460
+ async function generateManageBlocksPrompt(args) {
1461
+ const { action = "list", blockName = "\u5757\u540D", insertPoint = "0,0", scale = "1" } = args;
1462
+ const pt = insertPoint.split(",").map(Number);
1463
+ const codeMap = {
1464
+ list: `(block:list)`,
1465
+ insert: `(block:insert "${blockName}" "${blockName}" (list ${pt[0] || 0} ${pt[1] || 0}) 0 ${scale})`,
1466
+ attributes: `(block:get-attributes (car (pickset:to-list (ssget "_X" (list (cons 2 "${blockName}"))))))`,
1467
+ dynprops: `(block:get-dynamic-properties (car (pickset:to-list (ssget "_X" (list (cons 2 "${blockName}"))))))`
1468
+ };
1469
+ const code = codeMap[action] || codeMap.list;
1470
+ const descMap = {
1471
+ list: "\u5217\u51FA\u5F53\u524D\u56FE\u7EB8\u4E2D\u6240\u6709\u5757\u5B9A\u4E49",
1472
+ insert: `\u63D2\u5165\u5757 "${blockName}" \u5230\u70B9 (${pt[0] || 0}, ${pt[1] || 0})\uFF0C\u6BD4\u4F8B ${scale}`,
1473
+ attributes: `\u83B7\u53D6\u5757 "${blockName}" \u7684\u5C5E\u6027\u6807\u7B7E-\u503C\u5217\u8868`,
1474
+ dynprops: `\u83B7\u53D6\u52A8\u6001\u5757 "${blockName}" \u7684\u53EF\u8C03\u5C5E\u6027`
1475
+ };
1476
+ return {
1477
+ messages: [{
1478
+ role: "user",
1479
+ content: {
1480
+ type: "text",
1481
+ text: `${descMap[action] || descMap.list}
1482
+
1483
+ \`\`\`lisp
1484
+ ${code}
1485
+ \`\`\`
1486
+
1487
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1488
+ }
1489
+ }]
1490
+ };
1491
+ }
1492
+ async function generateCurveAnalysisPrompt(args) {
1493
+ const { action = "inters", distance = "100" } = args;
1494
+ const codeMap = {
1495
+ inters: `(progn
1496
+ (setq ss (ssget "_X" (list (cons 0 "LWPOLYLINE,LINE,ARC,CIRCLE"))))
1497
+ (if (and ss (>= (sslength ss) 2))
1498
+ (progn
1499
+ (setq elst (pickset:to-list ss))
1500
+ (setq e1 (car elst) e2 (cadr elst))
1501
+ (curve:inters e1 e2 0)
1502
+ )
1503
+ )
1504
+ )`,
1505
+ subsegments: `(progn
1506
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "LWPOLYLINE"))))))
1507
+ (if e (curve:subsegments e))
1508
+ )`,
1509
+ closestpoint: `(progn
1510
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "LWPOLYLINE,LINE,ARC,CIRCLE"))))))
1511
+ (if e (curve:pickclosepointto e (getpoint "\\n\u9009\u62E9\u53C2\u8003\u70B9: ")))
1512
+ )`,
1513
+ join: `(progn
1514
+ (setq ss (ssget (list (cons 0 "LINE,LWPOLYLINE"))))
1515
+ (if ss (curve:join (pickset:to-list ss) ${distance}))
1516
+ )`
1517
+ };
1518
+ const code = codeMap[action] || codeMap.inters;
1519
+ const descMap = {
1520
+ inters: "\u9009\u62E9\u524D\u4E24\u4E2A\u66F2\u7EBF\u5BF9\u8C61\uFF0C\u8BA1\u7B97\u5176\u4EA4\u70B9\uFF08\u53EF\u6307\u5B9A LWPOLYLINE, LINE, ARC, CIRCLE\uFF09",
1521
+ subsegments: "\u9009\u62E9\u4E00\u4E2ALWPOLYLINE\uFF0C\u8FD4\u56DE\u5176\u5B50\u6BB5\u6570",
1522
+ closestpoint: "\u9009\u62E9\u4E00\u4E2A\u66F2\u7EBF\u5BF9\u8C61\uFF0C\u7136\u540E\u62FE\u53D6\u4E00\u4E2A\u70B9\uFF0C\u8FD4\u56DE\u66F2\u7EBF\u4E0A\u79BB\u8BE5\u70B9\u6700\u8FD1\u7684\u70B9",
1523
+ join: "\u9009\u62E9LINE/LWPOLYLINE\u7EBF\u6BB5\uFF0C\u7528 PEDIT Join \u5408\u5E76\uFF0C\u5BB9\u5DEE\u8DDD\u79BB=" + distance
1524
+ };
1525
+ return {
1526
+ messages: [{
1527
+ role: "user",
1528
+ content: {
1529
+ type: "text",
1530
+ text: `\u66F2\u7EBF\u64CD\u4F5C\uFF1A${descMap[action] || descMap.inters}
1531
+
1532
+ \`\`\`lisp
1533
+ ${code}
1534
+ \`\`\`
1535
+
1536
+ \u63D0\u793A\uFF1A\u786E\u4FDD CAD \u4E2D\u5DF2\u6709\u5BF9\u5E94\u56FE\u5F62\u5BF9\u8C61\u3002`
1537
+ }
1538
+ }]
1539
+ };
1540
+ }
1541
+ async function generateGeometryCalcPrompt(args) {
1542
+ const { action = "centroid", points = "0,0;100,0;100,100;0,100" } = args;
1543
+ const ptList = points.split(";").map((p) => {
1544
+ const [x, y] = p.split(",").map(Number);
1545
+ return `(list ${x} ${y})`;
1546
+ });
1547
+ const ptsStr = `(list ${ptList.join(" ")})`;
1548
+ const codeMap = {
1549
+ centroid: `(point:centroid ${ptsStr})`,
1550
+ "convexhull": `(geometry:convexhull-by-graham-scan ${ptsStr})`,
1551
+ "dist-point-line": `(progn
1552
+ (setq ss (ssget ":S" (list (cons 0 "LINE"))))
1553
+ (if ss
1554
+ (progn
1555
+ (setq e (car (pickset:to-list ss)))
1556
+ (setq p1 (cdr (assoc 10 (entget e))))
1557
+ (setq p2 (cdr (assoc 11 (entget e))))
1558
+ (geometry:dist-pt-line (getpoint "\\n\u9009\u62E9\u6D4B\u91CF\u70B9: ") (list p1 p2))
1559
+ )
1560
+ )
1561
+ )`,
1562
+ "in-curve-p": `(progn
1563
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "LWPOLYLINE"))))))
1564
+ (if e (point:in-curve-p (getpoint "\\n\u9009\u62E9\u6D4B\u8BD5\u70B9: ") e))
1565
+ )`,
1566
+ transform: `(matrix:transformation (list 0 0 0) (list 2 2 1) 0 (list 0 0 0))`
1567
+ };
1568
+ const code = codeMap[action] || codeMap.centroid;
1569
+ const descMap = {
1570
+ centroid: `\u8BA1\u7B97 ${points} \u7684\u51E0\u4F55\u4E2D\u5FC3\uFF08\u8D28\u5FC3\uFF09`,
1571
+ convexhull: `\u8BA1\u7B97 ${points} \u7684\u51F8\u5305\uFF08Graham Scan \u7B97\u6CD5\uFF09`,
1572
+ "dist-point-line": "\u9009\u62E9\u4E00\u6761\u76F4\u7EBF\uFF0C\u7136\u540E\u62FE\u53D6\u4E00\u4E2A\u70B9\uFF0C\u8BA1\u7B97\u70B9\u5230\u76F4\u7EBF\u7684\u8DDD\u79BB",
1573
+ "in-curve-p": "\u9009\u62E9\u4E00\u4E2A\u95ED\u5408 LWPOLYLINE\uFF0C\u7136\u540E\u62FE\u53D6\u4E00\u4E2A\u70B9\uFF0C\u68C0\u6D4B\u70B9\u662F\u5426\u5728\u66F2\u7EBF\u5185\u90E8",
1574
+ transform: "\u5750\u6807\u53D8\u6362\u793A\u4F8B\uFF1A\u7F29\u653E2\u500D (matrix:transformation \u5E73\u79FB \u7F29\u653E \u65CB\u8F6C \u57FA\u70B9)"
1575
+ };
1576
+ return {
1577
+ messages: [{
1578
+ role: "user",
1579
+ content: {
1580
+ type: "text",
1581
+ text: `\u51E0\u4F55\u8BA1\u7B97\uFF1A${descMap[action] || descMap.centroid}
1582
+
1583
+ \`\`\`lisp
1584
+ ${code}
1585
+ \`\`\`
1586
+
1587
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1588
+ }
1589
+ }]
1590
+ };
1591
+ }
1592
+ async function generateTextProcessPrompt(args) {
1593
+ const { action = "remove-fmt", markdown = "\u8FD9\u662F **\u7C97\u4F53** \u548C *\u659C\u4F53* \u6587\u672C" } = args;
1594
+ const codeMap = {
1595
+ "remove-fmt": `(progn
1596
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "MTEXT"))))))
1597
+ (if e (text:remove-fmt (cdr (assoc 1 (entget e)))))
1598
+ )`,
1599
+ "parse-mtext": `(progn
1600
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "MTEXT"))))))
1601
+ (if e (text:parse-mtext (cdr (assoc 1 (entget e)))))
1602
+ )`,
1603
+ "from-markdown": `(text:from-markdown "${markdown}")`,
1604
+ "mtext2text": `(progn
1605
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "MTEXT"))))))
1606
+ (if e (text:mtext2text e))
1607
+ )`
1608
+ };
1609
+ const code = codeMap[action] || codeMap["remove-fmt"];
1610
+ const descMap = {
1611
+ "remove-fmt": "\u9009\u62E9\u4E00\u4E2AMTEXT\u5BF9\u8C61\uFF0C\u53BB\u9664\u6240\u6709\u683C\u5F0F\u4EE3\u7801\uFF0C\u8FD4\u56DE\u7EAF\u6587\u672C",
1612
+ "parse-mtext": "\u9009\u62E9\u4E00\u4E2AMTEXT\u5BF9\u8C61\uFF0C\u89E3\u6790\u4E3A (\u683C\u5F0F\u6216\u6587\u672C . \u5185\u5BB9) \u5217\u8868",
1613
+ "from-markdown": `\u5C06Markdown\u8F6C\u6362\u4E3AMTEXT\u683C\u5F0F\u4EE3\u7801\uFF1A
1614
+ ${markdown}`,
1615
+ "mtext2text": "\u9009\u62E9\u4E00\u4E2AMTEXT\u5BF9\u8C61\uFF0C\u5206\u89E3\u4E3A\u591A\u4E2A\u5355\u884CTEXT"
1616
+ };
1617
+ return {
1618
+ messages: [{
1619
+ role: "user",
1620
+ content: {
1621
+ type: "text",
1622
+ text: `\u6587\u672C\u5904\u7406\uFF1A${descMap[action] || descMap["remove-fmt"]}
1623
+
1624
+ \`\`\`lisp
1625
+ ${code}
1626
+ \`\`\`
1627
+
1628
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1629
+ }
1630
+ }]
1631
+ };
1632
+ }
1633
+ async function generatePicksetFilterPrompt(args) {
1634
+ const { action = "by-type", dxfType = "LINE", layerName = "0" } = args;
1635
+ const codeMap = {
1636
+ "by-type": `(progn
1637
+ (setq ss (ssget "_X" (list (cons 0 "${dxfType}"))))
1638
+ (if ss (list (sslength ss) (mapcar (function (lambda (x) (cdr (assoc 0 (entget x))))) (pickset:to-list ss))))
1639
+ )`,
1640
+ "by-layer": `(progn
1641
+ (setq ss (ssget "_X" (list (cons 8 "${layerName}"))))
1642
+ (if ss (list (sslength ss) (mapcar (function (lambda (x) (cdr (assoc 0 (entget x))))) (pickset:to-list ss))))
1643
+ )`,
1644
+ "by-box": `(progn
1645
+ (setq ss (ssget "_X"))
1646
+ (if ss (pickset:getbox ss 0))
1647
+ )`,
1648
+ erase: `(progn
1649
+ (setq ss (ssget (list (cons 0 "${dxfType}"))))
1650
+ (if ss (progn (pickset:erase ss) (princ (strcat "\u5DF2\u5220\u9664 " (itoa (sslength ss)) " \u4E2A " "${dxfType}" " \u5B9E\u4F53"))))
1651
+ )`,
1652
+ zoom: `(progn
1653
+ (setq ss (ssget "_X" (list (cons 0 "${dxfType}"))))
1654
+ (if ss (pickset:zoom ss))
1655
+ )`
1656
+ };
1657
+ const code = codeMap[action] || codeMap["by-type"];
1658
+ const descMap = {
1659
+ "by-type": `\u7EDF\u8BA1\u6240\u6709\u7C7B\u578B\u4E3A ${dxfType} \u7684\u5B9E\u4F53\u6570\u91CF`,
1660
+ "by-layer": `\u7EDF\u8BA1\u56FE\u5C42 ${layerName} \u4E0A\u7684\u5B9E\u4F53\u6570\u91CF\u548C\u7C7B\u578B`,
1661
+ "by-box": "\u8BA1\u7B97\u5168\u56FE\u9009\u62E9\u96C6\u7684\u8FB9\u754C\u6846",
1662
+ erase: `\u5220\u9664\u6240\u6709 ${dxfType} \u7C7B\u578B\u7684\u5B9E\u4F53`,
1663
+ zoom: `\u7F29\u653E\u5230\u6240\u6709 ${dxfType} \u7C7B\u578B\u7684\u5B9E\u4F53`
1664
+ };
1665
+ return {
1666
+ messages: [{
1667
+ role: "user",
1668
+ content: {
1669
+ type: "text",
1670
+ text: `\u9009\u62E9\u96C6\u64CD\u4F5C\uFF1A${descMap[action] || descMap["by-type"]}
1671
+
1672
+ \`\`\`lisp
1673
+ ${code}
1674
+ \`\`\`
1675
+
1676
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1677
+ }
1678
+ }]
1679
+ };
1680
+ }
1681
+ async function generateColorConvertPrompt(args) {
1682
+ const { action = "aci2rgb", value = "1" } = args;
1683
+ const codeMap = {
1684
+ aci2rgb: `(color:aci2rgb ${parseInt(value) || 1})`,
1685
+ rgb2css: `(color:rgb2css (list ${value.split(",").map((v) => parseInt(v) || 0).join(" ")}))`,
1686
+ truecolor2rgb: `(color:truecolor2rgb ${parseInt(value) || 16711680})`,
1687
+ rgb2truecolor: `(color:rgb2truecolor (list ${value.split(",").map((v) => parseInt(v) || 0).join(" ")}))`,
1688
+ rgb: `(color:rgb ${value.split(",").map((v) => parseInt(v) || 0).join(" ")})`
1689
+ };
1690
+ const code = codeMap[action] || codeMap.aci2rgb;
1691
+ const descMap = {
1692
+ aci2rgb: `ACI\u989C\u8272\u7D22\u5F15 ${value} \u8F6CRGB`,
1693
+ rgb2css: `RGB (${value || "255,0,0"}) \u8F6CCSS\u989C\u8272 #FFFFFF`,
1694
+ truecolor2rgb: `TrueColor\u6574\u6570 ${value} \u8F6CRGB\u5217\u8868`,
1695
+ rgb2truecolor: `RGB (${value || "255,0,0"}) \u8F6CTrueColor\u6574\u6570`,
1696
+ rgb: `\u8BA1\u7B97RGB\u5408\u6210\u503C\uFF1AR ${value.split(",")[0] || 255} G ${value.split(",")[1] || 0} B ${value.split(",")[2] || 0}`
1697
+ };
1698
+ return {
1699
+ messages: [{
1700
+ role: "user",
1701
+ content: {
1702
+ type: "text",
1703
+ text: `${descMap[action] || descMap.aci2rgb}
1704
+
1705
+ \`\`\`lisp
1706
+ ${code}
1707
+ \`\`\`
1708
+
1709
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1710
+ }
1711
+ }]
1712
+ };
1713
+ }
1714
+ async function generateJsonExchangePrompt(args) {
1715
+ const { action = "encode", data = '(("name" . "\u5BA2\u5385") ("area" . 45.5) ("layer" . "A-WALL"))' } = args;
1716
+ const codeMap = {
1717
+ encode: `(json:encode-from-alist '${data})`,
1718
+ decode: `(json:parse "${data.replace(/"/g, '\\"')}")`,
1719
+ "decode-json": `(json:decode-json-from-string "${data.replace(/"/g, '\\"')}")`
1720
+ };
1721
+ const code = codeMap[action] || codeMap.encode;
1722
+ const descMap = {
1723
+ encode: `\u5C06alist\u6570\u636E\u7F16\u7801\u4E3AJSON\u5B57\u7B26\u4E32`,
1724
+ decode: `\u4F7F\u7528\u7EAFLisp\u89E3\u6790\u5668\u89E3\u6790JSON\u5B57\u7B26\u4E32`,
1725
+ "decode-json": `\u4F7F\u7528\u670D\u52A1\u5668API\u89E3\u7801JSON\u5B57\u7B26\u4E32\uFF08\u652F\u6301GBK\u7F16\u7801\uFF09`
1726
+ };
1727
+ return {
1728
+ messages: [{
1729
+ role: "user",
1730
+ content: {
1731
+ type: "text",
1732
+ text: `JSON\u6570\u636E\u4EA4\u6362\uFF1A${descMap[action] || descMap.encode}
1733
+
1734
+ \`\`\`lisp
1735
+ ${code}
1736
+ \`\`\`
1737
+
1738
+ \u6570\u636E:
1739
+ ${data}
1740
+
1741
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1742
+ }
1743
+ }]
1744
+ };
1745
+ }
1746
+ async function generateExcelReportPrompt(args) {
1747
+ const { visible = "false", savePath = "" } = args;
1748
+ const code = `(progn
1749
+ ;; 1. \u7EDF\u8BA1\u56FE\u7EB8\u5B9E\u4F53
1750
+ (setq ss (ssget "_X"))
1751
+ (setq elst (if ss (pickset:to-list ss) nil))
1752
+ (setq type-count (if elst (stat:stat (mapcar (function (lambda (x) (cdr (assoc 0 (entget x))))) elst)) nil))
1753
+
1754
+ ;; 2. \u521B\u5EFAExcel
1755
+ (setq xl (excel:new ${visible === "true" ? "nil" : "t"}))
1756
+
1757
+ ;; 3. \u5199\u8868\u5934
1758
+ (excel:set-rangevalue xl 1 "\u5B9E\u4F53\u7C7B\u578B")
1759
+ (excel:set-rangevalue xl "B1" "\u6570\u91CF")
1760
+
1761
+ ;; 4. \u5199\u5165\u6570\u636E
1762
+ (setq row 2)
1763
+ (foreach item type-count
1764
+ (excel:set-rangevalue xl (list row 1) (car item))
1765
+ (excel:set-rangevalue xl (list row 2) (cdr item))
1766
+ (setq row (1+ row))
1767
+ )
1768
+
1769
+ ;; 5. \u83B7\u53D6\u56FE\u5C42\u5217\u8868
1770
+ (setq layers (layer:list))
1771
+ (excel:set-rangevalue xl (list 1 4) "\u56FE\u5C42\u5217\u8868")
1772
+ (setq row 2)
1773
+ (foreach lay layers
1774
+ (excel:set-rangevalue xl (list row 4) lay)
1775
+ (setq row (1+ row))
1776
+ )
1777
+
1778
+ ${savePath ? `(excel:saveas xl "${savePath}")` : ""}
1779
+ (princ (strcat "Excel\u62A5\u8868\u5DF2\u751F\u6210\uFF0C\u5171 " (itoa (1- row)) " \u884C\u6570\u636E"))
1780
+ )`;
1781
+ return {
1782
+ messages: [{
1783
+ role: "user",
1784
+ content: {
1785
+ type: "text",
1786
+ text: `\u5BFC\u51FACAD\u5B9E\u4F53\u7EDF\u8BA1\u5230Excel\u62A5\u8868\uFF1A
1787
+
1788
+ \`\`\`lisp
1789
+ ${code}
1790
+ \`\`\`
1791
+ ${savePath ? `
1792
+ \u4FDD\u5B58\u8DEF\u5F84: ${savePath}` : "\n\u6CE8\u610F\uFF1A\u8BF7\u66FF\u6362Excel\u4E3A\u53EF\u89C1\u6A21\u5F0F\u540E\u624B\u52A8\u4FDD\u5B58"}
1793
+
1794
+ \u4F7F\u7528 \`eval_lisp\` \u6267\u884C\u3002`
1795
+ }
1796
+ }]
1797
+ };
1798
+ }
1799
+ async function generateStringProcessPrompt(args) {
1800
+ const { action = "format", input = "Hello, {0}!", arg1 = "World", arg2 = "" } = args;
1801
+ const codeMap = {
1802
+ format: `(string:format "${input}" (list "${arg1}"))`,
1803
+ split: `(string:split "${input}" "${arg1}")`,
1804
+ "subst-all": `(string:subst-all "${arg2}" "${arg1}" "${input}")`,
1805
+ regexp: `(re:match "${arg1}" "${input}")`,
1806
+ trim: `(string:trim-space "${input}")`,
1807
+ number2chinese: `(string:number2chinese ${parseInt(input) || 12345})`,
1808
+ "to-list": `(string:to-list "${input}" "${arg1}")`
1809
+ };
1810
+ const code = codeMap[action] || codeMap.format;
1811
+ const descMap = {
1812
+ format: `\u683C\u5F0F\u5316: ${input} \u53C2\u6570: ${arg1}`,
1813
+ split: `\u62C6\u5206: "${input}" \u6309 "${arg1}" \u5206\u9694`,
1814
+ "subst-all": `\u66FF\u6362: \u5C06 "${input}" \u4E2D\u7684 "${arg1}" \u66FF\u6362\u4E3A "${arg2}"`,
1815
+ regexp: `\u6B63\u5219\u5339\u914D: "${input}" \u6A21\u5F0F: ${arg1}`,
1816
+ trim: `\u53BB\u9664\u9996\u5C3E\u7A7A\u683C: "${input}"`,
1817
+ number2chinese: `\u6570\u5B57 ${parseInt(input) || 12345} \u8F6C\u4E2D\u6587\u5927\u5199`,
1818
+ "to-list": `\u6309\u5206\u9694\u7B26 "${arg1}" \u62C6\u5206 "${input}" \u4E3A\u5217\u8868`
1819
+ };
1820
+ return {
1821
+ messages: [{
1822
+ role: "user",
1823
+ content: {
1824
+ type: "text",
1825
+ text: `${descMap[action] || descMap.format}
1826
+
1827
+ \`\`\`lisp
1828
+ ${code}
1829
+ \`\`\`
1830
+
1831
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1832
+ }
1833
+ }]
1834
+ };
1835
+ }
1370
1836
 
1371
1837
  // src/session-manager.js
1372
1838
  var Session = class {
@@ -1579,11 +2045,9 @@ var SseSession = class {
1579
2045
  return lines.join("\n") + "\n\n";
1580
2046
  }
1581
2047
  _setupDrain() {
1582
- if (typeof this.#res.on !== "function")
1583
- return;
2048
+ if (typeof this.#res.on !== "function") return;
1584
2049
  this.#drainHandler = () => {
1585
- if (!this.#active)
1586
- return;
2050
+ if (!this.#active) return;
1587
2051
  if (this.#backpressureBuffer.length > 0) {
1588
2052
  this._drainBuffer();
1589
2053
  }
@@ -1605,8 +2069,7 @@ var SseSession = class {
1605
2069
  }
1606
2070
  }
1607
2071
  _write(content) {
1608
- if (!this.#active)
1609
- return false;
2072
+ if (!this.#active) return false;
1610
2073
  try {
1611
2074
  if (this.#backpressureBuffer.length > 0) {
1612
2075
  this.#backpressureBuffer.push(content);
@@ -1876,8 +2339,7 @@ var SERVER_CAPABILITIES = {
1876
2339
  prompts: {}
1877
2340
  };
1878
2341
  var { port, host, transport, apiKey, rateLimitWindow, rateLimitMax } = config_default;
1879
- if (apiKey)
1880
- log("API Key authentication enabled");
2342
+ if (apiKey) log("API Key authentication enabled");
1881
2343
  var mcpLimiter = rateLimit({
1882
2344
  windowMs: rateLimitWindow,
1883
2345
  max: rateLimitMax,
@@ -1927,8 +2389,7 @@ ${CAD_PLATFORMS.join("\n")}
1927
2389
  list_symbols: (a) => listSymbols(a.package),
1928
2390
  import_funlib: async (a) => {
1929
2391
  const data = await loadAtlibFunctionLib();
1930
- if (!data)
1931
- return { content: [{ type: "text", text: "\u52A0\u8F7D\u51FD\u6570\u5E93\u5931\u8D25" }], isError: true };
2392
+ if (!data) return { content: [{ type: "text", text: "\u52A0\u8F7D\u51FD\u6570\u5E93\u5931\u8D25" }], isError: true };
1932
2393
  if (a.format === "list") {
1933
2394
  const items = Object.values(data.all_functions || {}).map((f) => `${f.name}: ${f.description || ""}`);
1934
2395
  return { content: [{ type: "text", text: items.join("\n") }] };
@@ -2090,8 +2551,7 @@ var tools = [
2090
2551
  ];
2091
2552
  async function handleToolCall(name, args) {
2092
2553
  const handler = TOOL_HANDLERS[name];
2093
- if (!handler)
2094
- return { content: [{ type: "text", text: `\u672A\u77E5\u5DE5\u5177: ${name}` }], isError: true };
2554
+ if (!handler) return { content: [{ type: "text", text: `\u672A\u77E5\u5DE5\u5177: ${name}` }], isError: true };
2095
2555
  try {
2096
2556
  const result = await handler(args || {});
2097
2557
  notifyResourceChanges(name);
@@ -2212,8 +2672,7 @@ async function startServer() {
2212
2672
  const JSON_CONTENT_TYPES = ["application/json", "application/json-rpc", "application/vnd.api+json"];
2213
2673
  app.use(async (req, res, next) => {
2214
2674
  const ct = (req.headers["content-type"] || "").toLowerCase();
2215
- if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
2216
- return next();
2675
+ if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t))) return next();
2217
2676
  try {
2218
2677
  const buf = await rawBody(req, { limit: "10mb" });
2219
2678
  const m = ct.match(/charset\s*=\s*([^\s;]+)/i);
@@ -2234,11 +2693,9 @@ async function startServer() {
2234
2693
  const PUBLIC_PATHS = ["/health"];
2235
2694
  if (apiKey) {
2236
2695
  app.use((req, res, next) => {
2237
- if (PUBLIC_PATHS.includes(req.path))
2238
- return next();
2696
+ if (PUBLIC_PATHS.includes(req.path)) return next();
2239
2697
  const auth = req.get("Authorization");
2240
- if (auth === `Bearer ${apiKey}`)
2241
- return next();
2698
+ if (auth === `Bearer ${apiKey}`) return next();
2242
2699
  res.status(401).json({ error: "Unauthorized" });
2243
2700
  });
2244
2701
  }
@@ -2253,8 +2710,7 @@ async function startServer() {
2253
2710
  res.setHeader("Access-Control-Expose-Headers", "mcp-session-id, content-type, x-accel-buffering");
2254
2711
  res.setHeader("Access-Control-Max-Age", "86400");
2255
2712
  res.setHeader("Vary", "Accept");
2256
- if (req.method === "OPTIONS")
2257
- return res.status(204).end();
2713
+ if (req.method === "OPTIONS") return res.status(204).end();
2258
2714
  next();
2259
2715
  });
2260
2716
  }
@@ -129,7 +129,7 @@ const cadSendWithResult = edge.func(function() {/*
129
129
  string platform = d.platform.ToString();
130
130
  string encoding = d.encoding != null ? d.encoding.ToString() : "";
131
131
  string progId = platform + ".Application";
132
- string tempDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "@lisp");
132
+ string tempDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "@lisp", "tmp");
133
133
  System.IO.Directory.CreateDirectory(tempDir);
134
134
 
135
135
  tempFile = System.IO.Path.Combine(tempDir, "atlisp_result_" + System.Guid.NewGuid().ToString("N") + ".txt");
@@ -440,6 +440,17 @@ async function handleMessage(msg) {
440
440
  if (!parenCheck.valid) {
441
441
  return { success: false, error: `括号错误: ${parenCheck.error} (位置 ${parenCheck.pos})` };
442
442
  }
443
+ if (msg.code.length > 255) {
444
+ log(`send (long code ${msg.code.length} chars, fallback to sendResult): ${msg.code.substring(0, 80)}...`);
445
+ const r = await new Promise((resolve, reject) => {
446
+ cadSendWithResult({ code: msg.code, platform: msg.platform || 'AutoCAD', encoding: '' }, (e, r) => {
447
+ if (e) reject(e);
448
+ else resolve(r);
449
+ });
450
+ });
451
+ log(`send result (long code): ${JSON.stringify(r)}`);
452
+ return r;
453
+ }
443
454
  const maxRetries = 3;
444
455
  let lastError = null;
445
456
  for (let i = 0; i < maxRetries; i++) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/mcp",
3
- "version": "1.3.4",
3
+ "version": "1.3.7",
4
4
  "description": "MCP Server for @lisp on CAD",
5
5
  "type": "module",
6
6
  "bin": {