@atlisp/mcp 1.8.0 → 1.8.2

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.
@@ -70,8 +70,7 @@ function parseArgs() {
70
70
  return result;
71
71
  }
72
72
  function loadConfigFile(filePath) {
73
- if (!filePath || !fs.existsSync(filePath))
74
- return null;
73
+ if (!filePath || !fs.existsSync(filePath)) return null;
75
74
  try {
76
75
  const raw = fs.readFileSync(filePath, "utf-8");
77
76
  const parsed = JSON.parse(raw);
@@ -215,6 +214,7 @@ __export(cad_exports, {
215
214
  cad: () => cad,
216
215
  default: () => cad_default,
217
216
  getWorker: () => getWorker,
217
+ onDocumentChanged: () => onDocumentChanged,
218
218
  resetWorker: () => resetWorker,
219
219
  sendMessage: () => sendMessage
220
220
  });
@@ -222,6 +222,20 @@ import { spawn } from "child_process";
222
222
  import path2 from "path";
223
223
  import { fileURLToPath } from "url";
224
224
  import { randomUUID } from "crypto";
225
+ function onDocumentChanged(callback) {
226
+ _docChangeCallbacks.push(callback);
227
+ }
228
+ function emitDocumentChanged(info) {
229
+ if (info.docName === _activeDocName) return;
230
+ _activeDocName = info.docName || "";
231
+ for (const cb of _docChangeCallbacks) {
232
+ try {
233
+ cb(info);
234
+ } catch (e) {
235
+ console.error("doc change callback error:", e.message);
236
+ }
237
+ }
238
+ }
225
239
  function resetWorker() {
226
240
  for (const [id, { reject, timeout }] of pendingRequests) {
227
241
  clearTimeout(timeout);
@@ -271,8 +285,7 @@ function setupStdoutHandler(w) {
271
285
  const lines = buffer.split("\n");
272
286
  buffer = lines.pop() || "";
273
287
  for (const line of lines) {
274
- if (!line.trim())
275
- continue;
288
+ if (!line.trim()) continue;
276
289
  try {
277
290
  const result = JSON.parse(line);
278
291
  const rid = result.requestId;
@@ -285,6 +298,8 @@ function setupStdoutHandler(w) {
285
298
  } else {
286
299
  resolve(result);
287
300
  }
301
+ } else if (result.type === "event" && result.eventType === "documentChanged") {
302
+ emitDocumentChanged({ docName: result.docName, docPath: result.docPath });
288
303
  }
289
304
  } catch (parseErr) {
290
305
  console.error("JSON parse error in worker output:", parseErr.message);
@@ -298,8 +313,7 @@ function setupStdoutHandler(w) {
298
313
  }
299
314
  function getWorker(force = false) {
300
315
  if (!worker || !worker.connected || force) {
301
- if (worker)
302
- worker.kill();
316
+ if (worker) worker.kill();
303
317
  worker = spawn("node", [workerPath], {
304
318
  stdio: ["pipe", "pipe", "pipe"]
305
319
  });
@@ -307,8 +321,7 @@ function getWorker(force = false) {
307
321
  const w = worker;
308
322
  w.on("exit", (code) => {
309
323
  console.error("worker exited with code:", code);
310
- if (w !== worker)
311
- return;
324
+ if (w !== worker) return;
312
325
  w.connected = false;
313
326
  for (const [id, { reject, timeout }] of pendingRequests) {
314
327
  clearTimeout(timeout);
@@ -329,14 +342,23 @@ function getWorker(force = false) {
329
342
  return worker;
330
343
  }
331
344
  function startHeartbeat() {
332
- if (heartbeatTimer)
333
- clearInterval(heartbeatTimer);
345
+ if (heartbeatTimer) clearInterval(heartbeatTimer);
334
346
  heartbeatTimer = setInterval(async () => {
335
347
  try {
336
348
  const result = await sendMessage({ type: "ping" });
337
349
  if (!result?.pong) {
338
350
  console.error("heartbeat failed, worker may be dead");
339
351
  resetWorker();
352
+ return;
353
+ }
354
+ if (_platform) {
355
+ try {
356
+ const docResult = await sendMessage({ type: "getActiveDocInfo", platform: _platform });
357
+ if (docResult?.docName) {
358
+ emitDocumentChanged({ docName: docResult.docName, docPath: docResult.docPath || "" });
359
+ }
360
+ } catch (e) {
361
+ }
340
362
  }
341
363
  } catch (e) {
342
364
  console.error("heartbeat error:", e.message);
@@ -365,7 +387,7 @@ function sendMessage(msg) {
365
387
  }
366
388
  });
367
389
  }
368
- var MESSAGE_TIMEOUT, HEARTBEAT_INTERVAL, MAX_RESTART_ATTEMPTS, RESTART_BACKOFF_BASE, __dirname, workerPath, worker, _platform, heartbeatTimer, pendingRequests, stdoutHandlerSetup, MAX_BUFFER_SIZE, restartCount, restartTimer, PRIORITY_NORMAL, MAX_QUEUE_SIZE, CommandQueue, commandQueue, CadConnection, cad, cad_default;
390
+ var MESSAGE_TIMEOUT, HEARTBEAT_INTERVAL, MAX_RESTART_ATTEMPTS, RESTART_BACKOFF_BASE, __dirname, workerPath, worker, _platform, heartbeatTimer, pendingRequests, stdoutHandlerSetup, MAX_BUFFER_SIZE, restartCount, restartTimer, PRIORITY_NORMAL, MAX_QUEUE_SIZE, _docChangeCallbacks, _activeDocName, _monitorStarted, CommandQueue, commandQueue, CadConnection, cad, cad_default;
369
391
  var init_cad = __esm({
370
392
  "src/cad.js"() {
371
393
  init_constants();
@@ -386,6 +408,9 @@ var init_cad = __esm({
386
408
  restartTimer = null;
387
409
  PRIORITY_NORMAL = 1;
388
410
  MAX_QUEUE_SIZE = 500;
411
+ _docChangeCallbacks = [];
412
+ _activeDocName = null;
413
+ _monitorStarted = false;
389
414
  CommandQueue = class {
390
415
  #queues = [[], [], []];
391
416
  #processing = false;
@@ -418,16 +443,13 @@ var init_cad = __esm({
418
443
  return null;
419
444
  }
420
445
  async _process() {
421
- if (this.#processing)
422
- return;
446
+ if (this.#processing) return;
423
447
  this.#processing = true;
424
448
  while (this._hasPending()) {
425
449
  const cmd = this._dequeue();
426
- if (!cmd)
427
- continue;
450
+ if (!cmd) continue;
428
451
  const dedupKey = this._dedupKey(cmd);
429
- if (dedupKey)
430
- this.#dedupMap.delete(dedupKey);
452
+ if (dedupKey) this.#dedupMap.delete(dedupKey);
431
453
  try {
432
454
  const result = await sendMessage(cmd);
433
455
  cmd.resolve(result);
@@ -442,8 +464,7 @@ var init_cad = __esm({
442
464
  }
443
465
  _dequeue() {
444
466
  for (const q of this.#queues) {
445
- if (q.length > 0)
446
- return q.shift();
467
+ if (q.length > 0) return q.shift();
447
468
  }
448
469
  return null;
449
470
  }
@@ -471,8 +492,7 @@ var init_cad = __esm({
471
492
  return process.platform === "win32";
472
493
  }
473
494
  async connect(platform = null) {
474
- if (!this.isAvailable())
475
- return false;
495
+ if (!this.isAvailable()) return false;
476
496
  try {
477
497
  const msg = platform ? { type: "connect", platform } : { type: "connect" };
478
498
  const result = await sendMessage(msg);
@@ -481,6 +501,13 @@ var init_cad = __esm({
481
501
  this.product = result.platform;
482
502
  _platform = result.platform;
483
503
  this.connected = true;
504
+ _activeDocName = null;
505
+ if (!_monitorStarted) {
506
+ _monitorStarted = true;
507
+ sendMessage({ type: "startMonitor", platform: _platform }).catch(() => {
508
+ _monitorStarted = false;
509
+ });
510
+ }
484
511
  return true;
485
512
  }
486
513
  } catch (e) {
@@ -489,8 +516,7 @@ var init_cad = __esm({
489
516
  return false;
490
517
  }
491
518
  async sendCommand(code) {
492
- if (!this.connected)
493
- throw new Error("\u672A\u8FDE\u63A5 CAD");
519
+ if (!this.connected) throw new Error("\u672A\u8FDE\u63A5 CAD");
494
520
  return new Promise((resolve, reject) => {
495
521
  commandQueue.enqueue({
496
522
  type: "send",
@@ -500,14 +526,12 @@ var init_cad = __esm({
500
526
  reject
501
527
  }, PRIORITY_NORMAL);
502
528
  }).then((result) => {
503
- if (result.success)
504
- return true;
529
+ if (result.success) return true;
505
530
  throw new Error(result.error || "\u53D1\u9001\u5931\u8D25");
506
531
  });
507
532
  }
508
533
  async sendCommandWithResult(code, encoding = null) {
509
- if (!this.connected)
510
- throw new Error("\u672A\u8FDE\u63A5 CAD");
534
+ if (!this.connected) throw new Error("\u672A\u8FDE\u63A5 CAD");
511
535
  return new Promise((resolve, reject) => {
512
536
  commandQueue.enqueue({
513
537
  type: "sendResult",
@@ -518,8 +542,7 @@ var init_cad = __esm({
518
542
  reject
519
543
  }, PRIORITY_NORMAL);
520
544
  }).then((result) => {
521
- if (result.success)
522
- return result.result || "";
545
+ if (result.success) return result.result || "";
523
546
  throw new Error(result.error || "\u53D1\u9001\u5931\u8D25");
524
547
  });
525
548
  }
@@ -530,8 +553,7 @@ var init_cad = __esm({
530
553
  return this.product;
531
554
  }
532
555
  async isBusy() {
533
- if (!this.connected)
534
- return false;
556
+ if (!this.connected) return false;
535
557
  try {
536
558
  const result = await sendMessage({ type: "isBusy", platform: _platform });
537
559
  return result && result.isBusy;
@@ -540,8 +562,7 @@ var init_cad = __esm({
540
562
  }
541
563
  }
542
564
  async hasDoc() {
543
- if (!this.connected)
544
- return { hasDoc: false, docCount: 0 };
565
+ if (!this.connected) return { hasDoc: false, docCount: 0 };
545
566
  try {
546
567
  const result = await sendMessage({ type: "hasdoc", platform: _platform });
547
568
  return result || { hasDoc: false, docCount: 0 };
@@ -550,8 +571,7 @@ var init_cad = __esm({
550
571
  }
551
572
  }
552
573
  async newDoc() {
553
- if (!this.connected)
554
- throw new Error("\u672A\u8FDE\u63A5 CAD");
574
+ if (!this.connected) throw new Error("\u672A\u8FDE\u63A5 CAD");
555
575
  try {
556
576
  const result = await sendMessage({ type: "newdoc", platform: _platform });
557
577
  return result && result.success;
@@ -560,8 +580,7 @@ var init_cad = __esm({
560
580
  }
561
581
  }
562
582
  async bringToFront() {
563
- if (!this.connected)
564
- throw new Error("\u672A\u8FDE\u63A5 CAD");
583
+ if (!this.connected) throw new Error("\u672A\u8FDE\u63A5 CAD");
565
584
  try {
566
585
  const result = await sendMessage({ type: "bringToFront", platform: _platform });
567
586
  return result && result.success;
@@ -569,9 +588,17 @@ var init_cad = __esm({
569
588
  return false;
570
589
  }
571
590
  }
591
+ async getActiveDocInfo() {
592
+ if (!this.connected) return { docName: "", docPath: "", docCount: 0 };
593
+ try {
594
+ const result = await sendMessage({ type: "getActiveDocInfo", platform: _platform });
595
+ return result || { docName: "", docPath: "", docCount: 0 };
596
+ } catch (e) {
597
+ return { docName: "", docPath: "", docCount: 0 };
598
+ }
599
+ }
572
600
  async getInfo() {
573
- if (!this.connected)
574
- return "CAD \u672A\u8FDE\u63A5";
601
+ if (!this.connected) return "CAD \u672A\u8FDE\u63A5";
575
602
  return `Platform: ${this.product}, Version: ${this.version}, Status: Connected`;
576
603
  }
577
604
  async disconnect() {
@@ -579,6 +606,8 @@ var init_cad = __esm({
579
606
  this.version = null;
580
607
  this.product = null;
581
608
  _platform = null;
609
+ _activeDocName = null;
610
+ _monitorStarted = false;
582
611
  commandQueue.clear();
583
612
  resetWorker();
584
613
  }
@@ -595,6 +624,8 @@ var init_cad = __esm({
595
624
  this.version = null;
596
625
  this.product = null;
597
626
  _platform = null;
627
+ _activeDocName = null;
628
+ _monitorStarted = false;
598
629
  commandQueue.clear();
599
630
  resetWorker();
600
631
  }
@@ -612,16 +643,14 @@ __export(renderer_exports, {
612
643
  renderTemplate: () => renderTemplate
613
644
  });
614
645
  function escapeLispString2(str) {
615
- if (typeof str !== "string")
616
- return "";
646
+ if (typeof str !== "string") return "";
617
647
  return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
618
648
  }
619
649
  function resolvePath(obj, path12) {
620
650
  const parts = path12.split(/[.\[\]]/g).filter(Boolean);
621
651
  let val = obj;
622
652
  for (const p of parts) {
623
- if (val == null)
624
- return void 0;
653
+ if (val == null) return void 0;
625
654
  val = val[p];
626
655
  }
627
656
  return val;
@@ -630,11 +659,9 @@ function renderTemplate(template, args) {
630
659
  return template.replace(PARAM_RE, (match, rawExpr, expr) => {
631
660
  const path12 = rawExpr || expr;
632
661
  const val = resolvePath(args, path12);
633
- if (val == null)
634
- return "";
662
+ if (val == null) return "";
635
663
  const strVal = String(val);
636
- if (rawExpr)
637
- return strVal;
664
+ if (rawExpr) return strVal;
638
665
  return escapeLispString2(strVal);
639
666
  });
640
667
  }
@@ -693,9 +720,8 @@ import express2 from "express";
693
720
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
694
721
 
695
722
  // src/logger.js
696
- init_config();
697
723
  import fs2 from "fs";
698
- import fsp from "fs/promises";
724
+ init_config();
699
725
  import path3 from "path";
700
726
  import os2 from "os";
701
727
  var DEBUG_FILE = config_default.debugFile || path3.join(os2.tmpdir(), "mcp-server-debug.log");
@@ -704,11 +730,9 @@ var MAX_LOG_FILES = 5;
704
730
  var stream = null;
705
731
  function rotateLog() {
706
732
  try {
707
- if (!fs2.existsSync(DEBUG_FILE))
708
- return;
733
+ if (!fs2.existsSync(DEBUG_FILE)) return;
709
734
  const stat = fs2.statSync(DEBUG_FILE);
710
- if (stat.size < MAX_LOG_SIZE)
711
- return;
735
+ if (stat.size < MAX_LOG_SIZE) return;
712
736
  if (stream) {
713
737
  stream.end();
714
738
  stream = null;
@@ -782,11 +806,9 @@ function ensureRequestLogDir() {
782
806
  }
783
807
  function rotateRequestLog() {
784
808
  try {
785
- if (!fs2.existsSync(REQUEST_LOG_FILE))
786
- return;
809
+ if (!fs2.existsSync(REQUEST_LOG_FILE)) return;
787
810
  const stat = fs2.statSync(REQUEST_LOG_FILE);
788
- if (stat.size < 10 * 1024 * 1024)
789
- return;
811
+ if (stat.size < 10 * 1024 * 1024) return;
790
812
  if (requestStream) {
791
813
  requestStream.end();
792
814
  requestStream = null;
@@ -811,8 +833,7 @@ function rotateRequestLog() {
811
833
  }
812
834
  }
813
835
  function logRequest(req) {
814
- if (!config_default.requestLogEnabled)
815
- return;
836
+ if (!config_default.requestLogEnabled) return;
816
837
  try {
817
838
  ensureRequestLogDir();
818
839
  rotateRequestLog();
@@ -833,8 +854,7 @@ function logRequest(req) {
833
854
  }
834
855
  }
835
856
  function logResponse(req, res, duration) {
836
- if (!config_default.requestLogEnabled)
837
- return;
857
+ if (!config_default.requestLogEnabled) return;
838
858
  try {
839
859
  ensureRequestLogDir();
840
860
  if (!requestStream) {
@@ -890,36 +910,27 @@ var TBL_QUERIES = {
890
910
  (setq @d nil)
891
911
  (vlax-for e (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
892
912
  (if (not (and (vlax-property-available-p e 'isfoundation) (vlax-get e 'isfoundation)))
893
- (setq @d (cons (list (cons 2 (vla-get-name e)) (cons 70 (if (and (vlax-property-available-p e 'isxref) (vlax-get e 'isxref)) 1 0))) @d))))
913
+ (setq @d (cons (@:get-props e '("Name" "Count" "Handle" "ObjectName" "IsXRef" "IsXRefOverlay" "IsDynamicBlock" "HasAttributes" "HasExtensionDictionary" "Path" "Description" "Layout" "BlockScope")) @d))))
894
914
  (list (cons 'table 'block) (cons 'total (length @d)) (cons 'data (list (reverse @d)))))` },
895
915
  style: { name: "style", lisp: `(progn
896
916
  (setq @d nil)
897
917
  (vlax-for e (vla-get-textstyles (vla-get-activedocument (vlax-get-acad-object)))
898
- (setq @d (cons (list
899
- (cons 2 (vla-get-name e))
900
- (cons 1 (vla-get-fontfile e))
901
- (cons 3 (vla-get-bigfontfile e))
902
- (cons 40 (vla-get-height e))
903
- (cons 41 (vla-get-width e))
904
- (cons 42 (/ (* 180.0 (vla-get-obliqueangle e)) pi))
905
- (cons 70 (vla-get-textgenerationflag e))
906
- ) @d)))
918
+ (setq @d (cons (@:get-props e '("Name" "FontFile" "BigFontFile" "Height" "Width" "ObliqueAngle" "TextGenerationFlag" "Handle" "ObjectName")) @d)))
907
919
  (list (cons 'table 'style) (cons 'total (length @d)) (cons 'data (list (reverse @d)))))` },
908
920
  dimstyle: { name: "dimstyle", lisp: `(progn
909
921
  (setq @d nil)
910
922
  (vlax-for e (vla-get-dimstyles (vla-get-activedocument (vlax-get-acad-object)))
911
- (setq @d (cons (list (cons 2 (vla-get-name e)) (cons 70 0)) @d)))
923
+ (setq @d (cons (@:get-props e '("Name" "Handle" "ObjectName")) @d)))
912
924
  (list (cons 'table 'dimstyle) (cons 'total (length @d)) (cons 'data (list (reverse @d)))))` },
913
925
  ltype: { name: "linetype", lisp: `(progn
914
926
  (setq @d nil)
915
927
  (vlax-for e (vla-get-linetypes (vla-get-activedocument (vlax-get-acad-object)))
916
- (setq @d (cons (list (cons 2 (vla-get-name e)) (cons 70 0)) @d)))
928
+ (setq @d (cons (@:get-props e '("Name" "Description" "PatternLength" "Handle" "ObjectName")) @d)))
917
929
  (list (cons 'table 'linetype) (cons 'total (length @d)) (cons 'data (list (reverse @d)))))` }
918
930
  };
919
931
  var TBL_KEY_ALIAS = {
920
932
  textstyle: "style",
921
933
  textstyles: "style",
922
- ltype: "linetype",
923
934
  linetype: "ltype"
924
935
  };
925
936
 
@@ -1022,27 +1033,21 @@ async function ensureCadConnected() {
1022
1033
  }
1023
1034
  }
1024
1035
  function escapeLispString(str) {
1025
- if (typeof str !== "string")
1026
- return "";
1036
+ if (typeof str !== "string") return "";
1027
1037
  return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1028
1038
  }
1029
1039
  function tryNumber(val) {
1030
- if (typeof val === "number")
1031
- return val;
1040
+ if (typeof val === "number") return val;
1032
1041
  const n = Number(val);
1033
- if (!isNaN(n) && val !== "")
1034
- return n;
1042
+ if (!isNaN(n) && val !== "") return n;
1035
1043
  return val;
1036
1044
  }
1037
1045
  function parseLispList(str) {
1038
- if (!str || typeof str !== "string")
1039
- return null;
1046
+ if (!str || typeof str !== "string") return null;
1040
1047
  const trimmed = str.trim();
1041
- if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
1042
- return null;
1048
+ if (!trimmed.startsWith("(") || !trimmed.endsWith(")")) return null;
1043
1049
  const content = trimmed.slice(1, -1).trim();
1044
- if (!content)
1045
- return [];
1050
+ if (!content) return [];
1046
1051
  const result = [];
1047
1052
  let depth = 0;
1048
1053
  let current = "";
@@ -1084,39 +1089,29 @@ function parseLispList(str) {
1084
1089
  }
1085
1090
  current += ch;
1086
1091
  }
1087
- if (current.trim())
1088
- result.push(current.trim());
1092
+ if (current.trim()) result.push(current.trim());
1089
1093
  return result.map((item) => {
1090
1094
  const t = item.trim();
1091
- if (t === "nil" || t === "NIL")
1092
- return null;
1093
- if (t === "t" || t === "T")
1094
- return true;
1095
- if (t.startsWith('"') && t.endsWith('"'))
1096
- return t.slice(1, -1);
1095
+ if (t === "nil" || t === "NIL") return null;
1096
+ if (t === "t" || t === "T") return true;
1097
+ if (t.startsWith('"') && t.endsWith('"')) return t.slice(1, -1);
1097
1098
  return tryNumber(t);
1098
1099
  });
1099
1100
  }
1100
1101
  function parseLispRecursive(str) {
1101
- if (!str || typeof str !== "string")
1102
- return null;
1102
+ if (!str || typeof str !== "string") return null;
1103
1103
  str = str.trim();
1104
- if (!str)
1105
- return null;
1104
+ if (!str) return null;
1106
1105
  let pos = 0;
1107
1106
  function skipWs() {
1108
- while (pos < str.length && /\s/.test(str[pos]))
1109
- pos++;
1107
+ while (pos < str.length && /\s/.test(str[pos])) pos++;
1110
1108
  }
1111
1109
  function parseValue() {
1112
1110
  skipWs();
1113
- if (pos >= str.length)
1114
- return null;
1111
+ if (pos >= str.length) return null;
1115
1112
  const ch = str[pos];
1116
- if (ch === "(")
1117
- return parseList();
1118
- if (ch === '"')
1119
- return parseString();
1113
+ if (ch === "(") return parseList();
1114
+ if (ch === '"') return parseString();
1120
1115
  if (ch === "'") {
1121
1116
  pos++;
1122
1117
  return parseValue();
@@ -1129,16 +1124,11 @@ function parseLispRecursive(str) {
1129
1124
  while (pos < str.length && str[pos] !== '"') {
1130
1125
  if (str[pos] === "\\" && pos + 1 < str.length) {
1131
1126
  pos++;
1132
- if (str[pos] === '"')
1133
- r += '"';
1134
- else if (str[pos] === "n")
1135
- r += "\n";
1136
- else if (str[pos] === "t")
1137
- r += " ";
1138
- else if (str[pos] === "\\")
1139
- r += "\\";
1140
- else
1141
- r += str[pos];
1127
+ if (str[pos] === '"') r += '"';
1128
+ else if (str[pos] === "n") r += "\n";
1129
+ else if (str[pos] === "t") r += " ";
1130
+ else if (str[pos] === "\\") r += "\\";
1131
+ else r += str[pos];
1142
1132
  } else {
1143
1133
  r += str[pos];
1144
1134
  }
@@ -1149,13 +1139,10 @@ function parseLispRecursive(str) {
1149
1139
  }
1150
1140
  function parseAtom() {
1151
1141
  const start = pos;
1152
- while (pos < str.length && !/\s/.test(str[pos]) && str[pos] !== ")" && str[pos] !== "(")
1153
- pos++;
1142
+ while (pos < str.length && !/\s/.test(str[pos]) && str[pos] !== ")" && str[pos] !== "(") pos++;
1154
1143
  const atom = str.slice(start, pos);
1155
- if (atom === "nil" || atom === "NIL")
1156
- return null;
1157
- if (atom === "t" || atom === "T")
1158
- return true;
1144
+ if (atom === "nil" || atom === "NIL") return null;
1145
+ if (atom === "t" || atom === "T") return true;
1159
1146
  return tryNumber(atom);
1160
1147
  }
1161
1148
  function parseList() {
@@ -1163,15 +1150,13 @@ function parseLispRecursive(str) {
1163
1150
  const items = [];
1164
1151
  while (pos < str.length) {
1165
1152
  skipWs();
1166
- if (pos >= str.length)
1167
- break;
1153
+ if (pos >= str.length) break;
1168
1154
  if (str[pos] === ")") {
1169
1155
  pos++;
1170
1156
  return items;
1171
1157
  }
1172
1158
  const left = parseValue();
1173
- if (left === void 0)
1174
- break;
1159
+ if (left === void 0) break;
1175
1160
  skipWs();
1176
1161
  if (str[pos] === "." && (pos + 1 >= str.length || /\s/.test(str[pos + 1]) || str[pos + 1] === ")")) {
1177
1162
  pos++;
@@ -1193,19 +1178,6 @@ function parseLispRecursive(str) {
1193
1178
  }
1194
1179
  return parseValue();
1195
1180
  }
1196
- function lispPairsToObject(pairs) {
1197
- if (!Array.isArray(pairs))
1198
- return pairs;
1199
- const obj = {};
1200
- for (let i = 0; i < pairs.length - 1; i += 2) {
1201
- const key = pairs[i];
1202
- const val = pairs[i + 1];
1203
- if (typeof key === "string" || typeof key === "number") {
1204
- obj[String(key)] = Array.isArray(val) ? lispPairsToObject(val) : val;
1205
- }
1206
- }
1207
- return obj;
1208
- }
1209
1181
 
1210
1182
  // src/handlers/resource-readers.js
1211
1183
  var ENTITY_PROPERTIES_LISP = `
@@ -1261,8 +1233,7 @@ var ENTITY_PROPERTIES_LISP = `
1261
1233
  result)
1262
1234
  `;
1263
1235
  function propertyPairsToObject(pairs) {
1264
- if (!Array.isArray(pairs))
1265
- return null;
1236
+ if (!Array.isArray(pairs)) return null;
1266
1237
  const obj = {};
1267
1238
  for (const pair of pairs) {
1268
1239
  if (Array.isArray(pair) && pair.length >= 2) {
@@ -1273,10 +1244,8 @@ function propertyPairsToObject(pairs) {
1273
1244
  }
1274
1245
  function buildEntityPropertiesCode({ type, layer, bbox }) {
1275
1246
  const items = [];
1276
- if (type)
1277
- items.push(`(cons 0 "${escapeLispString(type)}")`);
1278
- if (layer)
1279
- items.push(`(cons 8 "${escapeLispString(layer)}")`);
1247
+ if (type) items.push(`(cons 0 "${escapeLispString(type)}")`);
1248
+ if (layer) items.push(`(cons 8 "${escapeLispString(layer)}")`);
1280
1249
  if (bbox) {
1281
1250
  const parts = bbox.split(",").map((s) => parseFloat(s.trim()));
1282
1251
  if (parts.length === 4) {
@@ -1302,10 +1271,8 @@ ${ENTITY_PROPERTIES_LISP}
1302
1271
  (vl-prin1-to-string (list @e:total (reverse @e:ents))))`;
1303
1272
  }
1304
1273
  async function getEntityByHandle(handle) {
1305
- if (!cad.connected)
1306
- await cad.connect();
1307
- if (!cad.connected)
1308
- return { error: "CAD \u672A\u8FDE\u63A5" };
1274
+ if (!cad.connected) await cad.connect();
1275
+ if (!cad.connected) return { error: "CAD \u672A\u8FDE\u63A5" };
1309
1276
  const code = `(progn
1310
1277
  (vl-load-com)
1311
1278
  (if (setq ent (handent "${escapeLispString(handle)}"))
@@ -1325,8 +1292,7 @@ async function getEntityByHandle(handle) {
1325
1292
  )`;
1326
1293
  try {
1327
1294
  const result = await cad.sendCommandWithResult(code);
1328
- if (!result || result === "nil")
1329
- return { error: `\u672A\u627E\u5230\u5B9E\u4F53: ${handle}` };
1295
+ if (!result || result === "nil") return { error: `\u672A\u627E\u5230\u5B9E\u4F53: ${handle}` };
1330
1296
  try {
1331
1297
  return JSON.parse(result);
1332
1298
  } catch {
@@ -1338,8 +1304,7 @@ async function getEntityByHandle(handle) {
1338
1304
  }
1339
1305
  async function getCadInfo() {
1340
1306
  const cached = getCached("cad:info");
1341
- if (cached)
1342
- return cached;
1307
+ if (cached) return cached;
1343
1308
  if (!cad.connected) {
1344
1309
  await cad.connect();
1345
1310
  }
@@ -1364,10 +1329,8 @@ async function getCadInfo() {
1364
1329
  async function getEntities(params = {}) {
1365
1330
  const cacheKey = `dwg:entities:${JSON.stringify(params)}`;
1366
1331
  const cached = getCached(cacheKey);
1367
- if (cached)
1368
- return cached;
1369
- if (!cad.connected)
1370
- await cad.connect();
1332
+ if (cached) return cached;
1333
+ if (!cad.connected) await cad.connect();
1371
1334
  if (!cad.connected) {
1372
1335
  return { total: 0, entities: [] };
1373
1336
  }
@@ -1455,9 +1418,14 @@ async function getEntitiesSummary(cacheKey) {
1455
1418
  }
1456
1419
  }
1457
1420
  function buildTextContentCode({ layer, bbox, offset, limit }) {
1458
- const items = [`'(0 . "TEXT,MTEXT,ATTRIB,TCH_TEXT")`];
1459
- if (layer)
1460
- items.push(`(cons 8 "${escapeLispString(layer)}")`);
1421
+ const items = [
1422
+ `'(-4 . "<OR")`,
1423
+ `'(0 . "TEXT")`,
1424
+ `'(0 . "MTEXT")`,
1425
+ `'(0 . "ATTRIB")`,
1426
+ `'(-4 . "OR>")`
1427
+ ];
1428
+ if (layer) items.push(`(cons 8 "${escapeLispString(layer)}")`);
1461
1429
  if (bbox) {
1462
1430
  const parts = bbox.split(",").map((s) => parseFloat(s.trim()));
1463
1431
  if (parts.length === 4) {
@@ -1472,6 +1440,7 @@ function buildTextContentCode({ layer, bbox, offset, limit }) {
1472
1440
  }
1473
1441
  const filterExpr = `(list ${items.join(" ")})`;
1474
1442
  return `(progn
1443
+ (vl-load-com)
1475
1444
  (setq ss (ssget "_X" ${filterExpr}))
1476
1445
  (if (null ss)
1477
1446
  (list "total" 0 "offset" ${offset} "limit" ${limit} "texts" nil)
@@ -1481,15 +1450,13 @@ function buildTextContentCode({ layer, bbox, offset, limit }) {
1481
1450
  (setq ent (ssname ss i) ed (entget ent) ins (cdr (assoc 10 ed)))
1482
1451
  (setq texts (append texts (list (list "text" (vl-prin1-to-string (cdr (assoc 1 ed))) "position" (list (car ins) (cadr ins) (caddr ins))))) i (1+ i)))
1483
1452
  (list "total" total "offset" ${offset} "limit" ${limit} "texts" texts))))
1484
- )`;
1453
+ `;
1485
1454
  }
1486
1455
  async function getTextContent(params = {}) {
1487
1456
  const cacheKey = `dwg:text-content:${JSON.stringify(params)}`;
1488
1457
  const cached = getCached(cacheKey);
1489
- if (cached)
1490
- return cached;
1491
- if (!cad.connected)
1492
- await cad.connect();
1458
+ if (cached) return cached;
1459
+ if (!cad.connected) await cad.connect();
1493
1460
  if (!cad.connected) {
1494
1461
  return { total: 0, offset: 0, limit: 5e3, texts: [] };
1495
1462
  }
@@ -1498,42 +1465,47 @@ async function getTextContent(params = {}) {
1498
1465
  try {
1499
1466
  const code = buildTextContentCode({ layer: params.layer, bbox: params.bbox, offset, limit });
1500
1467
  const resultStr = await cad.sendCommandWithResult(code);
1501
- if (!resultStr || resultStr === "" || resultStr === "nil" || resultStr === "0") {
1502
- return { total: 0, offset, limit, texts: [] };
1503
- }
1468
+ log(`[DEBUG text-content] resultStr length=${resultStr?.length} first300=${resultStr?.substring(0, 300)}`);
1504
1469
  const parsed = parseLispRecursive(resultStr);
1505
1470
  if (!parsed || !Array.isArray(parsed)) {
1506
- return { total: 0, offset, limit, texts: [] };
1471
+ throw new Error(`text-content: \u89E3\u6790 Lisp \u7ED3\u679C\u5931\u8D25: raw="${String(resultStr).substring(0, 500)}"`);
1472
+ }
1473
+ const data = {};
1474
+ let rawTexts = [];
1475
+ for (let i = 0; i < parsed.length - 1; i += 2) {
1476
+ const key = parsed[i];
1477
+ const val = parsed[i + 1];
1478
+ if (typeof key === "string" || typeof key === "number") {
1479
+ if (key === "texts" && Array.isArray(val)) {
1480
+ rawTexts = val;
1481
+ } else {
1482
+ data[String(key)] = val;
1483
+ }
1484
+ }
1507
1485
  }
1508
- const data = lispPairsToObject(parsed);
1509
- const rawTexts = Array.isArray(data.texts) ? data.texts : [];
1510
1486
  data.texts = rawTexts.map((item) => {
1511
- if (!Array.isArray(item))
1512
- return null;
1487
+ if (!Array.isArray(item)) return null;
1513
1488
  const obj = {};
1514
- item.forEach((pair) => {
1515
- if (Array.isArray(pair) && pair.length >= 2) {
1516
- if (pair[0] === "text")
1517
- obj.text = String(pair[1] || "");
1518
- else if (pair[0] === "position" && Array.isArray(pair[1])) {
1519
- obj.position = pair[1].map((v) => typeof v === "number" ? v : 0);
1520
- }
1489
+ for (let i = 0; i < item.length - 1; i += 2) {
1490
+ const key = item[i];
1491
+ const val = item[i + 1];
1492
+ if (key === "text") obj.text = String(val || "");
1493
+ else if (key === "position") {
1494
+ obj.position = Array.isArray(val) ? val.map((v) => typeof v === "number" ? v : 0) : [];
1521
1495
  }
1522
- });
1496
+ }
1523
1497
  return obj.text ? obj : null;
1524
1498
  }).filter(Boolean);
1525
1499
  setCache(cacheKey, data);
1526
1500
  return data;
1527
1501
  } catch (e) {
1528
1502
  log(`getTextContent error: ${e.message}`);
1529
- return { total: 0, offset, limit, texts: [] };
1503
+ throw e;
1530
1504
  }
1531
1505
  }
1532
1506
  async function getDwgName() {
1533
- if (!cad.connected)
1534
- await cad.connect();
1535
- if (!cad.connected)
1536
- return { name: null };
1507
+ if (!cad.connected) await cad.connect();
1508
+ if (!cad.connected) return { name: null };
1537
1509
  try {
1538
1510
  const code = `(vl-princ-to-string (getvar "dwgname"))`;
1539
1511
  const name = await cad.sendCommandWithResult(code);
@@ -1543,10 +1515,8 @@ async function getDwgName() {
1543
1515
  }
1544
1516
  }
1545
1517
  async function getDwgPath() {
1546
- if (!cad.connected)
1547
- await cad.connect();
1548
- if (!cad.connected)
1549
- return { path: null, name: null };
1518
+ if (!cad.connected) await cad.connect();
1519
+ if (!cad.connected) return { path: null, name: null };
1550
1520
  try {
1551
1521
  const code = `(progn
1552
1522
  (setq prefix (vl-princ-to-string (getvar "dwgprefix")))
@@ -1565,8 +1535,7 @@ async function getDwgPath() {
1565
1535
  }
1566
1536
  if (!parsed) {
1567
1537
  const listResult = parseLispList(result);
1568
- if (listResult && listResult.length >= 2)
1569
- parsed = listResult;
1538
+ if (listResult && listResult.length >= 2) parsed = listResult;
1570
1539
  }
1571
1540
  if (parsed && Array.isArray(parsed) && parsed.length >= 2) {
1572
1541
  return { path: String(parsed[0]), name: String(parsed[1]) };
@@ -1577,100 +1546,92 @@ async function getDwgPath() {
1577
1546
  }
1578
1547
  }
1579
1548
  function buildBlockRefsCode(filterBlockName) {
1580
- const filterExpr = filterBlockName ? `(list (cons 2 "${escapeLispString(filterBlockName)}"))` : "nil";
1549
+ const filterItems = ['(cons 0 "INSERT")'];
1550
+ if (filterBlockName) {
1551
+ filterItems.push(`(cons 2 "${escapeLispString(filterBlockName)}")`);
1552
+ }
1553
+ const filterCode = `(list ${filterItems.join(" ")})`;
1581
1554
  return `(progn
1582
1555
  (vl-load-com)
1583
- (defun @br:attr (ent / atts)
1584
- (if (= (type ent) 'VLA-OBJECT)
1585
- (progn
1586
- (setq atts (vlax-variant-value (vla-getattributes ent)))
1587
- (if (safearray-value atts)
1588
- (mapcar '(lambda (x) (cons (vla-get-tagstring x) (vla-get-textstring x)))
1589
- (vlax-safearray->list atts))
1590
- nil))
1591
- (if (setq att (entnext ent))
1592
- (progn
1593
- (setq atts nil)
1594
- (while (= (cdr (assoc 0 (entget att))) "ATTRIB")
1595
- (setq atts (cons (cons (cdr (assoc 2 (entget att))) (cdr (assoc 1 (entget att)))) atts))
1596
- att (entnext att))
1597
- (reverse atts))
1598
- nil))))
1599
1556
 
1600
- (defun @br:dynprops (ent / obj props)
1601
- (if (= (type ent) 'VLA-OBJECT)
1557
+ (defun @br:try (obj prop / r)
1558
+ (if (vl-catch-all-error-p
1559
+ (setq r (vl-catch-all-apply
1560
+ (function (lambda () (vlax-get obj prop))))))
1561
+ nil
1562
+ r))
1563
+
1564
+ (defun @br:get-attrs (ent / att atts)
1565
+ (if (setq att (entnext ent))
1602
1566
  (progn
1603
- (setq obj ent)
1604
- (if (vlax-property-available-p obj 'isdynamicblock)
1605
- (if (vla-get-isdynamicblock obj)
1606
- (progn
1607
- (setq props (vlax-invoke obj 'getdynamicblockproperties))
1608
- (mapcar '(lambda (x)
1609
- (cons (vla-get-propertyname x)
1610
- (list (cons "value" (vla-get-value x))
1611
- (cons "readOnly" (vla-get-readonly x))
1612
- (cons "show" (vla-get-show x)))))
1613
- (vlax-safearray->list props)))
1614
- nil)
1615
- nil))
1616
- (if (and (setq obj (vlax-ename->vla-object ent))
1617
- (vlax-property-available-p obj 'isdynamicblock)
1618
- (vla-get-isdynamicblock obj))
1619
- (progn
1620
- (setq props (vlax-invoke obj 'getdynamicblockproperties))
1621
- (mapcar '(lambda (x)
1622
- (cons (vla-get-propertyname x)
1623
- (list (cons "value" (vla-get-value x))
1624
- (cons "readOnly" (vla-get-readonly x))
1625
- (cons "show" (vla-get-show x)))))
1626
- (vlax-safearray->list props)))
1627
- nil)))
1567
+ (setq atts nil)
1568
+ (while (= (cdr (assoc 0 (entget att))) "ATTRIB")
1569
+ (setq atts (cons (cons (cdr (assoc 2 (entget att))) (cdr (assoc 1 (entget att)))) atts))
1570
+ att (entnext att))
1571
+ (reverse atts))
1572
+ nil))
1628
1573
 
1629
- (defun @br:props (ent / obj blkname result)
1630
- (setq obj (vlax-ename->vla-object ent))
1631
- (setq result (list
1632
- (cons "handle" (cdr (assoc 5 (entget ent))))
1633
- (cons "layer" (cdr (assoc 8 (entget ent))))
1634
- (cons "blockName" (vla-get-name obj))
1635
- (cons "effectiveBlockName" (vla-get-effectivename obj))
1636
- (cons "insertionPoint" (vlax-safearray->list (vla-get-insertionpoint obj)))
1637
- (cons "rotation" (vla-get-rotation obj))
1638
- (cons "scale" (list (vla-get-xscale obj) (vla-get-yscale obj) (vla-get-zscale obj)))
1639
- (cons "isDynamic" (if (vlax-property-available-p obj 'isdynamicblock) (vla-get-isdynamicblock obj) nil))
1640
- (cons "attributes" (@br:attr obj))
1641
- (cons "dynamicProperties" (@br:dynprops obj))))
1642
- result)
1574
+ (defun @br:get-dynprops (obj / r)
1575
+ (setq r (vl-catch-all-apply
1576
+ (function (lambda ()
1577
+ (mapcar '(lambda (x)
1578
+ (cons (vla-get-propertyname x)
1579
+ (list (cons "value" (vlax-get x 'value))
1580
+ (cons "readOnly" (vlax-get x 'readonly))
1581
+ (cons "show" (vlax-get x 'show)))))
1582
+ (vlax-safearray->list (vlax-invoke obj 'getdynamicblockproperties)))))))
1583
+ (if (vl-catch-all-error-p r) nil r))
1584
+
1585
+ (defun @br:props (ent / obj ed r)
1586
+ (setq r (vl-catch-all-apply
1587
+ (function (lambda ()
1588
+ (setq obj (vlax-ename->vla-object ent)
1589
+ ed (entget ent))
1590
+ (list
1591
+ (cons "handle" (cdr (assoc 5 ed)))
1592
+ (cons "layer" (cdr (assoc 8 ed)))
1593
+ (cons "blockName" (vla-get-name obj))
1594
+ (cons "effectiveBlockName" (@br:try obj 'effectivename))
1595
+ (cons "insertionPoint" (vlax-safearray->list (vla-get-insertionpoint obj)))
1596
+ (cons "rotation" (vla-get-rotation obj))
1597
+ (cons "scale" (list (vla-get-xscale obj) (vla-get-yscale obj) (vla-get-zscale obj)))
1598
+ (cons "isDynamic" (@br:try obj 'isdynamicblock))
1599
+ (cons "attributes" (@br:get-attrs ent))
1600
+ (cons "dynamicProperties" (@br:get-dynprops obj)))))))
1601
+ (if (vl-catch-all-error-p r) nil r))
1643
1602
 
1644
- (setq ss (ssget "_X" (list (cons 0 "INSERT") ${filterExpr})))
1603
+ (setq ss (ssget "_X" ${filterCode}))
1645
1604
  (if (null ss)
1646
1605
  (list (cons "total" 0) (cons "blockRefs" nil))
1647
1606
  (progn
1648
1607
  (setq total (sslength ss) i 0 refs nil)
1649
1608
  (while (< i total)
1650
- (setq refs (cons (@br:props (ssname ss i)) refs) i (1+ i)))
1651
- (list (cons "total" total) (cons "blockRefs" (reverse refs))))))`;
1609
+ (setq r (@br:props (ssname ss i)))
1610
+ (if r (setq refs (cons r refs)))
1611
+ (setq i (1+ i)))
1612
+ (list (cons "total" total) (cons "blockRefs" (list (reverse refs)))))))`;
1652
1613
  }
1653
1614
  async function getBlockRefs(params = {}) {
1654
1615
  const cacheKey = `dwg:block-refs:${params.blockName || "all"}`;
1655
1616
  const cached = getCached(cacheKey);
1656
- if (cached)
1657
- return cached;
1658
- if (!cad.connected)
1659
- await cad.connect();
1617
+ if (cached) return cached;
1618
+ if (!cad.connected) await cad.connect();
1660
1619
  if (!cad.connected) {
1661
1620
  return { total: 0, blockRefs: [] };
1662
1621
  }
1663
1622
  try {
1664
1623
  const code = buildBlockRefsCode(params.blockName);
1665
1624
  const resultStr = await cad.sendCommandWithResult(code);
1666
- if (!resultStr || resultStr === "" || resultStr === "nil") {
1667
- return { total: 0, blockRefs: [] };
1668
- }
1669
1625
  const parsed = parseLispRecursive(resultStr);
1670
1626
  if (!parsed || !Array.isArray(parsed)) {
1671
- return { total: 0, blockRefs: [] };
1627
+ throw new Error(`block-refs: \u89E3\u6790 Lisp \u7ED3\u679C\u5931\u8D25: raw="${String(resultStr).substring(0, 500)}"`);
1628
+ }
1629
+ const result = {};
1630
+ for (const pair of parsed) {
1631
+ if (Array.isArray(pair) && pair.length >= 2) {
1632
+ result[String(pair[0])] = pair[1];
1633
+ }
1672
1634
  }
1673
- const result = lispPairsToObject(parsed);
1674
1635
  const blockRefs = Array.isArray(result.blockRefs) ? result.blockRefs : [];
1675
1636
  const finalResult = {
1676
1637
  total: typeof result.total === "number" ? result.total : blockRefs.length,
@@ -1680,7 +1641,7 @@ async function getBlockRefs(params = {}) {
1680
1641
  br.forEach((pair) => {
1681
1642
  if (Array.isArray(pair) && pair.length >= 2) {
1682
1643
  const key = pair[0];
1683
- let val = pair[1];
1644
+ let val = pair.length === 2 ? pair[1] : pair.slice(1);
1684
1645
  if (key === "insertionPoint" && Array.isArray(val)) {
1685
1646
  val = val.map((v) => typeof v === "number" ? v : 0);
1686
1647
  } else if (key === "scale" && Array.isArray(val)) {
@@ -1699,51 +1660,67 @@ async function getBlockRefs(params = {}) {
1699
1660
  return finalResult;
1700
1661
  } catch (e) {
1701
1662
  log(`getBlockRefs error: ${e.message}`);
1702
- return { total: 0, blockRefs: [] };
1663
+ throw e;
1703
1664
  }
1704
1665
  }
1666
+ var VLA_HELPER_LISP = `(defun @:get-props (obj prop-names / result p p-sym val)
1667
+ (setq result nil)
1668
+ (foreach p prop-names
1669
+ (setq p-sym (read p))
1670
+ (if (vlax-property-available-p obj p-sym)
1671
+ (progn
1672
+ (setq val (vl-catch-all-apply 'vlax-get (list obj p-sym)))
1673
+ (if (not (vl-catch-all-error-p val))
1674
+ (progn
1675
+ (cond
1676
+ ((= (type val) 'VLA-OBJECT) (setq val (strcat "@" (vla-get-objectname val))))
1677
+ ((or (= (type val) 'STR) (= (type val) 'SAFEARRAY) (listp val)) (setq val (vl-prin1-to-string val))))
1678
+ (setq result (cons (cons p val) result)))))))
1679
+ (reverse result))`;
1705
1680
  function buildTablesCode(tblName) {
1706
1681
  const raw = tblName.toLowerCase();
1707
1682
  const key = TBL_KEY_ALIAS[raw] || raw;
1708
1683
  const query = TBL_QUERIES[key];
1684
+ const isVlaTable = key !== "layer";
1709
1685
  if (query) {
1686
+ if (isVlaTable) {
1687
+ return `(progn (vl-load-com) ${VLA_HELPER_LISP} ${query.lisp})`;
1688
+ }
1710
1689
  return `(progn (vl-load-com) ${query.lisp})`;
1711
1690
  }
1712
- const parts = Object.values(TBL_QUERIES).map((q) => q.lisp);
1713
- return `(progn (vl-load-com) (list ${parts.join(" ")}))`;
1691
+ const parts = Object.values(TBL_QUERIES).map((q) => `(vl-catch-all-apply '(lambda () ${q.lisp}))`);
1692
+ return `(progn (vl-load-com) ${VLA_HELPER_LISP} (list ${parts.join(" ")}))`;
1714
1693
  }
1715
- function parseTableRecord(rec) {
1716
- if (!rec || !Array.isArray(rec))
1717
- return null;
1694
+ function parseTableRecord(rec, tableName) {
1695
+ if (!rec || !Array.isArray(rec)) return null;
1718
1696
  const obj = {};
1697
+ const isLayer = tableName === "layer";
1719
1698
  for (const pair of rec) {
1720
1699
  if (Array.isArray(pair) && pair.length >= 2) {
1721
1700
  const key = String(pair[0]);
1722
1701
  const val = pair[1];
1723
- if (key === "2")
1724
- obj.name = String(val);
1725
- else if (key === "62")
1726
- obj.color = typeof val === "number" ? val : 7;
1727
- else if (key === "6")
1728
- obj.linetype = String(val);
1729
- else if (key === "70") {
1730
- obj.flags = typeof val === "number" ? val : 0;
1731
- obj.frozen = (val & 1) !== 0;
1732
- obj.locked = (val & 4) !== 0;
1733
- } else if (key === "60")
1734
- obj.on = val === 0;
1735
- else if (key === "1")
1736
- obj.font = String(val);
1737
- else if (key === "40")
1738
- obj.height = typeof val === "number" ? val : 0;
1739
- else if (key === "41")
1740
- obj.width = typeof val === "number" ? val : 1;
1741
- else if (key === "42")
1742
- obj.oblique = typeof val === "number" ? val : 0;
1743
- else if (key === "3")
1744
- obj.bigfont = String(val);
1745
- else if (key === "50")
1746
- obj.flags = typeof val === "number" ? val : 0;
1702
+ const isDxfCode = typeof pair[0] === "number";
1703
+ if (isDxfCode) {
1704
+ if (key === "2") obj.name = String(val);
1705
+ else if (key === "62") obj.color = typeof val === "number" ? val : 7;
1706
+ else if (key === "6") obj.linetype = String(val);
1707
+ else if (key === "70") {
1708
+ obj.flags = typeof val === "number" ? val : 0;
1709
+ if (isLayer) {
1710
+ obj.frozen = (val & 1) !== 0;
1711
+ obj.locked = (val & 4) !== 0;
1712
+ }
1713
+ } else if (key === "60") obj.on = val === 0;
1714
+ else if (key === "1") obj.font = String(val);
1715
+ else if (key === "40") obj.height = typeof val === "number" ? val : 0;
1716
+ else if (key === "41") obj.width = typeof val === "number" ? val : 1;
1717
+ else if (key === "42") obj.oblique = typeof val === "number" ? val : 0;
1718
+ else if (key === "3") obj.bigfont = String(val);
1719
+ else if (key === "50") obj.flags = typeof val === "number" ? val : 0;
1720
+ } else {
1721
+ if (key === "Name") obj.name = val;
1722
+ obj[key] = val;
1723
+ }
1747
1724
  }
1748
1725
  }
1749
1726
  return obj.name ? obj : null;
@@ -1752,12 +1729,9 @@ async function getTables(params = {}) {
1752
1729
  const tblName = params.tbl || params.type || "all";
1753
1730
  const cacheKey = `dwg:tbl:${tblName}`;
1754
1731
  const cached = getCached(cacheKey);
1755
- if (cached)
1756
- return cached;
1757
- if (!cad.connected)
1758
- await cad.connect();
1759
- if (!cad.connected)
1760
- return { table: tblName, data: [] };
1732
+ if (cached) return cached;
1733
+ if (!cad.connected) await cad.connect();
1734
+ if (!cad.connected) return { table: tblName, data: [] };
1761
1735
  try {
1762
1736
  const code = buildTablesCode(tblName);
1763
1737
  const resultStr = await cad.sendCommandWithResult(code);
@@ -1776,10 +1750,9 @@ async function getTables(params = {}) {
1776
1750
  for (const item of parsed) {
1777
1751
  if (Array.isArray(item) && item.length >= 2) {
1778
1752
  const key = String(item[0]).toUpperCase();
1779
- if (key === "TOTAL")
1780
- total = typeof item[1] === "number" ? item[1] : 0;
1753
+ if (key === "TOTAL") total = typeof item[1] === "number" ? item[1] : 0;
1781
1754
  else if (key === "DATA") {
1782
- if (Array.isArray(item[1]) && item[1].length > 0 && item[1][0].length > 0 && !isNaN(parseInt(item[1][0][0]))) {
1755
+ if (Array.isArray(item[1]) && item[1].length > 0) {
1783
1756
  tblData = item[1];
1784
1757
  }
1785
1758
  }
@@ -1791,46 +1764,41 @@ async function getTables(params = {}) {
1791
1764
  result = {
1792
1765
  table: tableName,
1793
1766
  total,
1794
- data: tblData.map(parseTableRecord).filter(Boolean)
1767
+ data: tblData.map((r) => parseTableRecord(r, tableName)).filter(Boolean)
1795
1768
  };
1796
1769
  } else {
1797
1770
  const allData = {};
1798
1771
  parsed.forEach((item) => {
1799
- if (!Array.isArray(item) || item.length < 2)
1800
- return;
1772
+ if (!Array.isArray(item) || item.length < 2) return;
1801
1773
  let tableKey = null;
1802
1774
  const entry = { total: 0, data: [] };
1803
1775
  if (Array.isArray(item[0]) && item[0].length >= 2 && String(item[0][0]).toLowerCase() === "table") {
1804
1776
  tableKey = String(item[0][1]).toLowerCase();
1805
1777
  for (let i = 1; i < item.length; i++) {
1806
1778
  const sub = item[i];
1807
- if (!Array.isArray(sub) || sub.length < 2)
1808
- continue;
1779
+ if (!Array.isArray(sub) || sub.length < 2) continue;
1809
1780
  const subKey = String(sub[0]).toUpperCase();
1810
- if (subKey === "TOTAL")
1811
- entry.total = typeof sub[1] === "number" ? sub[1] : 0;
1781
+ if (subKey === "TOTAL") entry.total = typeof sub[1] === "number" ? sub[1] : 0;
1812
1782
  else if (subKey === "DATA") {
1813
1783
  const raw = Array.isArray(sub[1]) ? sub[1] : sub.slice(1);
1814
- entry.data = raw.map(parseTableRecord).filter(Boolean);
1784
+ entry.data = raw.map((r) => parseTableRecord(r, tableKey)).filter(Boolean);
1815
1785
  }
1816
1786
  }
1817
1787
  } else {
1818
1788
  tableKey = String(item[0]).toLowerCase();
1819
1789
  for (let i = 1; i < item.length; i++) {
1820
1790
  const sub = item[i];
1821
- if (!Array.isArray(sub) || sub.length < 2)
1822
- continue;
1791
+ if (!Array.isArray(sub) || sub.length < 2) continue;
1823
1792
  const subKey = String(sub[0]).toUpperCase();
1824
1793
  if (subKey === "TOTAL") {
1825
1794
  entry.total = typeof sub[1] === "number" ? sub[1] : 0;
1826
1795
  } else if (subKey === "DATA") {
1827
1796
  const raw = Array.isArray(sub[1]) ? sub[1] : sub.slice(1);
1828
- entry.data = raw.map(parseTableRecord).filter(Boolean);
1797
+ entry.data = raw.map((r) => parseTableRecord(r, tableKey)).filter(Boolean);
1829
1798
  }
1830
1799
  }
1831
1800
  }
1832
- if (tableKey)
1833
- allData[tableKey] = entry;
1801
+ if (tableKey) allData[tableKey] = entry;
1834
1802
  });
1835
1803
  result = allData;
1836
1804
  }
@@ -1844,12 +1812,9 @@ async function getTables(params = {}) {
1844
1812
  async function getPackages(filterName = null) {
1845
1813
  const cacheKey = filterName ? `packages:${filterName}` : "packages:all";
1846
1814
  const cached = getCached(cacheKey);
1847
- if (cached)
1848
- return cached;
1849
- if (!cad.connected)
1850
- await cad.connect();
1851
- if (!cad.connected)
1852
- return [];
1815
+ if (cached) return cached;
1816
+ if (!cad.connected) await cad.connect();
1817
+ if (!cad.connected) return [];
1853
1818
  try {
1854
1819
  const code = `(mapcar 'cdr @::*local-pkgs*)`;
1855
1820
  const result = await cad.sendCommandWithResult(code);
@@ -1862,8 +1827,7 @@ async function getPackages(filterName = null) {
1862
1827
  } catch {
1863
1828
  raw = parseLispList(result) || [];
1864
1829
  }
1865
- if (!Array.isArray(raw))
1866
- raw = [];
1830
+ if (!Array.isArray(raw)) raw = [];
1867
1831
  const packages = raw.map((item) => {
1868
1832
  if (Array.isArray(item)) {
1869
1833
  const pkg = { name: "", version: "0.0.0", description: "", loaded: true };
@@ -1872,20 +1836,13 @@ async function getPackages(filterName = null) {
1872
1836
  const [[key, val]] = Object.entries(entry);
1873
1837
  const k = String(key);
1874
1838
  const v = String(val);
1875
- if (k === ":NAME")
1876
- pkg.name = v;
1877
- else if (k === ":VERSION")
1878
- pkg.version = v;
1879
- else if (k === ":DESCRIPTION")
1880
- pkg.description = v;
1881
- else if (k === ":FULL-NAME")
1882
- pkg.fullName = v;
1883
- else if (k === ":AUTHOR")
1884
- pkg.author = v;
1885
- else if (k === ":CATEGORY")
1886
- pkg.category = v;
1887
- else if (k === ":URL")
1888
- pkg.url = v;
1839
+ if (k === ":NAME") pkg.name = v;
1840
+ else if (k === ":VERSION") pkg.version = v;
1841
+ else if (k === ":DESCRIPTION") pkg.description = v;
1842
+ else if (k === ":FULL-NAME") pkg.fullName = v;
1843
+ else if (k === ":AUTHOR") pkg.author = v;
1844
+ else if (k === ":CATEGORY") pkg.category = v;
1845
+ else if (k === ":URL") pkg.url = v;
1889
1846
  }
1890
1847
  }
1891
1848
  return pkg;
@@ -1896,22 +1853,15 @@ async function getPackages(filterName = null) {
1896
1853
  if (item && typeof item === "object") {
1897
1854
  const pkg = { name: "", version: "0.0.0", description: "", loaded: true };
1898
1855
  const nameVal = item.name || item.Name || item.NAME || item[":NAME"];
1899
- if (nameVal)
1900
- pkg.name = String(nameVal);
1856
+ if (nameVal) pkg.name = String(nameVal);
1901
1857
  const verVal = item.version || item.Version || item.VERSION || item[":VERSION"];
1902
- if (verVal)
1903
- pkg.version = String(verVal);
1858
+ if (verVal) pkg.version = String(verVal);
1904
1859
  const descVal = item.description || item.Description || item.DESCRIPTION || item[":DESCRIPTION"];
1905
- if (descVal)
1906
- pkg.description = String(descVal);
1907
- if (item.fullName || item.full_name)
1908
- pkg.fullName = String(item.fullName || item.full_name);
1909
- if (item.author || item.Author)
1910
- pkg.author = String(item.author || item.Author);
1911
- if (item.category || item.Category)
1912
- pkg.category = String(item.category || item.Category);
1913
- if (item.url || item.Url || item.URL)
1914
- pkg.url = String(item.url || item.Url || item.URL);
1860
+ if (descVal) pkg.description = String(descVal);
1861
+ if (item.fullName || item.full_name) pkg.fullName = String(item.fullName || item.full_name);
1862
+ if (item.author || item.Author) pkg.author = String(item.author || item.Author);
1863
+ if (item.category || item.Category) pkg.category = String(item.category || item.Category);
1864
+ if (item.url || item.Url || item.URL) pkg.url = String(item.url || item.Url || item.URL);
1915
1865
  return pkg;
1916
1866
  }
1917
1867
  return null;
@@ -1936,12 +1886,9 @@ function getPlatforms() {
1936
1886
  async function getDwgList() {
1937
1887
  const cacheKey = "cad:dwgs";
1938
1888
  const cached = getCached(cacheKey);
1939
- if (cached)
1940
- return cached;
1941
- if (!cad.connected)
1942
- await cad.connect();
1943
- if (!cad.connected)
1944
- return [];
1889
+ if (cached) return cached;
1890
+ if (!cad.connected) await cad.connect();
1891
+ if (!cad.connected) return [];
1945
1892
  try {
1946
1893
  const code = `(progn
1947
1894
  (vl-load-com)
@@ -1959,13 +1906,12 @@ async function getDwgList() {
1959
1906
  try {
1960
1907
  parsed = JSON.parse(result);
1961
1908
  } catch (e) {
1962
- const listResult = parseLispList(result);
1963
- if (listResult) {
1909
+ const listResult = parseLispRecursive(result);
1910
+ if (Array.isArray(listResult)) {
1964
1911
  parsed = listResult;
1965
1912
  }
1966
1913
  }
1967
- if (!Array.isArray(parsed))
1968
- parsed = [];
1914
+ if (!Array.isArray(parsed)) parsed = [];
1969
1915
  const dwgList = parsed.map((item) => {
1970
1916
  if (Array.isArray(item) && item.length >= 2) {
1971
1917
  return { name: String(item[0]), path: String(item[1]) };
@@ -1991,8 +1937,7 @@ function loadStandardsFile(filename) {
1991
1937
  var standardsCache = /* @__PURE__ */ new Map();
1992
1938
  function getCachedStandards(key) {
1993
1939
  const entry = standardsCache.get(key);
1994
- if (entry && Date.now() - entry.timestamp < 3e4)
1995
- return entry.data;
1940
+ if (entry && Date.now() - entry.timestamp < 3e4) return entry.data;
1996
1941
  standardsCache.delete(key);
1997
1942
  return null;
1998
1943
  }
@@ -2001,49 +1946,40 @@ function setCachedStandards(key, data) {
2001
1946
  }
2002
1947
  function getDraftingStandards() {
2003
1948
  const cached = getCachedStandards("drafting");
2004
- if (cached)
2005
- return cached;
1949
+ if (cached) return cached;
2006
1950
  const data = loadStandardsFile("drafting.json");
2007
- if (data)
2008
- setCachedStandards("drafting", data);
1951
+ if (data) setCachedStandards("drafting", data);
2009
1952
  return data || { error: "\u5236\u56FE\u89C4\u8303\u6587\u4EF6\u52A0\u8F7D\u5931\u8D25" };
2010
1953
  }
2011
1954
  function getCodingStandards() {
2012
1955
  const cached = getCachedStandards("coding");
2013
- if (cached)
2014
- return cached;
1956
+ if (cached) return cached;
2015
1957
  const data = loadStandardsFile("coding.json");
2016
- if (data)
2017
- setCachedStandards("coding", data);
1958
+ if (data) setCachedStandards("coding", data);
2018
1959
  return data || { error: "\u7F16\u7801\u89C4\u8303\u6587\u4EF6\u52A0\u8F7D\u5931\u8D25" };
2019
1960
  }
2020
1961
 
2021
1962
  // src/handlers/resource-handlers.js
2022
1963
  function parseQuery(uri) {
2023
1964
  const qIdx = uri.indexOf("?");
2024
- if (qIdx === -1)
2025
- return { base: uri, params: {} };
1965
+ if (qIdx === -1) return { base: uri, params: {} };
2026
1966
  const base = uri.substring(0, qIdx);
2027
1967
  const params = {};
2028
1968
  uri.substring(qIdx + 1).split("&").forEach((p) => {
2029
1969
  const eqIdx = p.indexOf("=");
2030
1970
  const k = eqIdx === -1 ? p : p.substring(0, eqIdx);
2031
1971
  const v = eqIdx === -1 ? "" : p.substring(eqIdx + 1);
2032
- if (k)
2033
- params[k] = decodeURIComponent(v);
1972
+ if (k) params[k] = decodeURIComponent(v);
2034
1973
  });
2035
1974
  return { base, params };
2036
1975
  }
2037
1976
  function parseTemplateUri(uri) {
2038
1977
  const entityMatch = uri.match(/^atlisp:\/\/dwg\/entity\/([^?]+)$/);
2039
- if (entityMatch)
2040
- return { type: "entity", handle: entityMatch[1] };
1978
+ if (entityMatch) return { type: "entity", handle: entityMatch[1] };
2041
1979
  const tblMatch = uri.match(/^atlisp:\/\/dwg\/tbl\/([^?]+)$/);
2042
- if (tblMatch)
2043
- return { type: "tbl", tblName: tblMatch[1] };
1980
+ if (tblMatch) return { type: "tbl", tblName: tblMatch[1] };
2044
1981
  const blockRefMatch = uri.match(/^atlisp:\/\/dwg\/block-refs\/([^?]+)$/);
2045
- if (blockRefMatch)
2046
- return { type: "block-refs", blockName: blockRefMatch[1] };
1982
+ if (blockRefMatch) return { type: "block-refs", blockName: blockRefMatch[1] };
2047
1983
  return null;
2048
1984
  }
2049
1985
  async function listResources(subscribedUris = []) {
@@ -2203,10 +2139,8 @@ function isPrefixUri(uri) {
2203
2139
  return uri.endsWith("/");
2204
2140
  }
2205
2141
  function matchesSubscription(subscribedUri, targetUri) {
2206
- if (subscribedUri === targetUri)
2207
- return true;
2208
- if (isPrefixUri(subscribedUri) && targetUri.startsWith(subscribedUri))
2209
- return true;
2142
+ if (subscribedUri === targetUri) return true;
2143
+ if (isPrefixUri(subscribedUri) && targetUri.startsWith(subscribedUri)) return true;
2210
2144
  return false;
2211
2145
  }
2212
2146
  function isSubscribed(uri, sessionId) {
@@ -2216,8 +2150,7 @@ function isSubscribed(uri, sessionId) {
2216
2150
  }
2217
2151
  const allUris = sessionManager.getAllSubscribedUris();
2218
2152
  for (const su of allUris) {
2219
- if (matchesSubscription(su, uri))
2220
- return true;
2153
+ if (matchesSubscription(su, uri)) return true;
2221
2154
  }
2222
2155
  return false;
2223
2156
  }
@@ -2326,11 +2259,9 @@ var SseSession = class {
2326
2259
  return lines.join("\n") + "\n\n";
2327
2260
  }
2328
2261
  _setupDrain() {
2329
- if (typeof this.#res.on !== "function")
2330
- return;
2262
+ if (typeof this.#res.on !== "function") return;
2331
2263
  this.#drainHandler = () => {
2332
- if (!this.#active)
2333
- return;
2264
+ if (!this.#active) return;
2334
2265
  if (this.#backpressureBuffer.length > 0) {
2335
2266
  this._drainBuffer();
2336
2267
  }
@@ -2352,8 +2283,7 @@ var SseSession = class {
2352
2283
  }
2353
2284
  }
2354
2285
  _write(content) {
2355
- if (!this.#active)
2356
- return false;
2286
+ if (!this.#active) return false;
2357
2287
  try {
2358
2288
  if (this.#backpressureBuffer.length > 0) {
2359
2289
  this.#backpressureBuffer.push(content);
@@ -2482,8 +2412,7 @@ function persistSessionData(clientId, sessionData) {
2482
2412
  function loadPersistedSessionData(clientId) {
2483
2413
  try {
2484
2414
  const filePath = getSessionStorePath(clientId);
2485
- if (!fs4.existsSync(filePath))
2486
- return null;
2415
+ if (!fs4.existsSync(filePath)) return null;
2487
2416
  const raw = fs4.readFileSync(filePath, "utf-8");
2488
2417
  const store = JSON.parse(raw);
2489
2418
  if (Date.now() - store.savedAt > SESSION_STORE_TTL) {
@@ -2547,8 +2476,7 @@ var SseSessionManager = class {
2547
2476
  session.close();
2548
2477
  this.#sessions.delete(clientId);
2549
2478
  const idx = this.#accessOrder.indexOf(clientId);
2550
- if (idx !== -1)
2551
- this.#accessOrder.splice(idx, 1);
2479
+ if (idx !== -1) this.#accessOrder.splice(idx, 1);
2552
2480
  return true;
2553
2481
  }
2554
2482
  return false;
@@ -2635,8 +2563,7 @@ var SseSessionManager = class {
2635
2563
  session.close();
2636
2564
  this.#sessions.delete(clientId);
2637
2565
  const idx = this.#accessOrder.indexOf(clientId);
2638
- if (idx !== -1)
2639
- this.#accessOrder.splice(idx, 1);
2566
+ if (idx !== -1) this.#accessOrder.splice(idx, 1);
2640
2567
  }
2641
2568
  }
2642
2569
  }
@@ -2684,8 +2611,7 @@ var SessionTransport = class {
2684
2611
  this._started = true;
2685
2612
  }
2686
2613
  async send(message) {
2687
- if (this._closed)
2688
- return;
2614
+ if (this._closed) return;
2689
2615
  if (this._pendingRequest) {
2690
2616
  const { resolve, reject, timeout } = this._pendingRequest;
2691
2617
  clearTimeout(timeout);
@@ -2694,8 +2620,7 @@ var SessionTransport = class {
2694
2620
  }
2695
2621
  }
2696
2622
  async close() {
2697
- if (this._closed)
2698
- return;
2623
+ if (this._closed) return;
2699
2624
  this._closed = true;
2700
2625
  if (this._pendingRequest) {
2701
2626
  const { reject, timeout } = this._pendingRequest;
@@ -2769,12 +2694,10 @@ var DEFS_DIR = path7.join(__dirname3, "definitions");
2769
2694
  var PROMPTS_DIR = path7.join(__dirname3, "..", "..", "prompts");
2770
2695
  var builtinDefs = null;
2771
2696
  function loadBuiltinDefs() {
2772
- if (builtinDefs)
2773
- return builtinDefs;
2697
+ if (builtinDefs) return builtinDefs;
2774
2698
  builtinDefs = {};
2775
2699
  try {
2776
- if (!fs5.existsSync(DEFS_DIR))
2777
- return builtinDefs;
2700
+ if (!fs5.existsSync(DEFS_DIR)) return builtinDefs;
2778
2701
  const files = fs5.readdirSync(DEFS_DIR).filter((f) => f.endsWith(".json"));
2779
2702
  for (const file of files) {
2780
2703
  try {
@@ -2836,15 +2759,12 @@ function formatLispPoints(pointsStr) {
2836
2759
  return `(list ${ptList.join(" ")})`;
2837
2760
  }
2838
2761
  function getDimensionStyleLisp(style) {
2839
- if (style === "horizontal" || style === "vertical")
2840
- return "DIMLINEAR";
2762
+ if (style === "horizontal" || style === "vertical") return "DIMLINEAR";
2841
2763
  return "DIMALIGNED";
2842
2764
  }
2843
2765
  function getDimensionStyleLabel(style) {
2844
- if (style === "horizontal")
2845
- return "\u6C34\u5E73";
2846
- if (style === "vertical")
2847
- return "\u5782\u76F4";
2766
+ if (style === "horizontal") return "\u6C34\u5E73";
2767
+ if (style === "vertical") return "\u5782\u76F4";
2848
2768
  return "aligned";
2849
2769
  }
2850
2770
  async function handleComplexPrompt(def, args) {
@@ -2878,14 +2798,10 @@ async function handleComplexPrompt(def, args) {
2878
2798
  } catch {
2879
2799
  }
2880
2800
  const suggestions = [];
2881
- if (entities.total > 1e3)
2882
- suggestions.push("- \u56FE\u7EB8\u5B9E\u4F53\u8F83\u591A\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u56FE\u5C42\u5206\u7C7B\u7BA1\u7406");
2883
- if (layers.length > 20)
2884
- suggestions.push("- \u56FE\u5C42\u8F83\u591A\uFF0C\u5EFA\u8BAE\u6E05\u7406\u672A\u4F7F\u7528\u7684\u56FE\u5C42");
2885
- if (entities.byType.LINE && entities.byType.LINE > 500)
2886
- suggestions.push("- \u7EBF\u6761\u8F83\u591A\uFF0C\u53EF\u8003\u8651\u4F7F\u7528 BLOCK \u51CF\u5C11\u5B9E\u4F53\u6570\u91CF");
2887
- if (!entities.byType.DIMENSION)
2888
- suggestions.push("- \u672A\u53D1\u73B0\u5C3A\u5BF8\u6807\u6CE8\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u6807\u6CE8");
2801
+ if (entities.total > 1e3) suggestions.push("- \u56FE\u7EB8\u5B9E\u4F53\u8F83\u591A\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u56FE\u5C42\u5206\u7C7B\u7BA1\u7406");
2802
+ if (layers.length > 20) suggestions.push("- \u56FE\u5C42\u8F83\u591A\uFF0C\u5EFA\u8BAE\u6E05\u7406\u672A\u4F7F\u7528\u7684\u56FE\u5C42");
2803
+ 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");
2804
+ if (!entities.byType.DIMENSION) suggestions.push("- \u672A\u53D1\u73B0\u5C3A\u5BF8\u6807\u6CE8\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u6807\u6CE8");
2889
2805
  return {
2890
2806
  messages: [{
2891
2807
  role: "user",
@@ -3078,8 +2994,7 @@ ${code}
3078
2994
  }
3079
2995
  const defs = loadBuiltinDefs();
3080
2996
  const def = defs[name];
3081
- if (!def)
3082
- throw new Error(`Unknown prompt: ${name}`);
2997
+ if (!def) throw new Error(`Unknown prompt: ${name}`);
3083
2998
  if (def.handler) {
3084
2999
  return handleComplexPrompt(def, args);
3085
3000
  }
@@ -3104,8 +3019,7 @@ import path8 from "path";
3104
3019
  init_config();
3105
3020
  var MAX_HISTORY_VALUES = 1e3;
3106
3021
  function percentile(sorted, p) {
3107
- if (sorted.length === 0)
3108
- return 0;
3022
+ if (sorted.length === 0) return 0;
3109
3023
  const idx = Math.ceil(p * sorted.length) - 1;
3110
3024
  return sorted[Math.max(0, Math.min(idx, sorted.length - 1))];
3111
3025
  }
@@ -3396,8 +3310,7 @@ async function evalLisp(code, withResult = false, encoding = null) {
3396
3310
  return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3397
3311
  }
3398
3312
  const trimmed = (code || "").trim();
3399
- if (!trimmed)
3400
- return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
3313
+ if (!trimmed) return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
3401
3314
  try {
3402
3315
  if (withResult) {
3403
3316
  const result = await cad.sendCommandWithResult(trimmed, encoding);
@@ -3417,17 +3330,14 @@ async function getCadInfo2() {
3417
3330
  if (!cad.connected) {
3418
3331
  await cad.connect();
3419
3332
  }
3420
- if (!cad.connected)
3421
- return { content: [{ type: "text", text: "CAD \u672A\u8FDE\u63A5" }] };
3333
+ if (!cad.connected) return { content: [{ type: "text", text: "CAD \u672A\u8FDE\u63A5" }] };
3422
3334
  const info = await cad.getInfo();
3423
3335
  return { content: [{ type: "text", text: info }] };
3424
3336
  }
3425
3337
  async function atCommand(command) {
3426
- if (!cad.connected)
3427
- return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
3338
+ if (!cad.connected) return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
3428
3339
  const trimmed = (command || "").trim();
3429
- if (!trimmed)
3430
- return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
3340
+ if (!trimmed) return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
3431
3341
  await cad.sendCommand(trimmed + "\n");
3432
3342
  return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001\u547D\u4EE4" }] };
3433
3343
  }
@@ -3435,8 +3345,7 @@ async function newDocument() {
3435
3345
  if (!cad.connected) {
3436
3346
  await cad.connect();
3437
3347
  }
3438
- if (!cad.connected)
3439
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3348
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3440
3349
  const result = await cad.newDoc();
3441
3350
  if (result) {
3442
3351
  return { content: [{ type: "text", text: "\u5DF2\u5728 CAD \u4E2D\u65B0\u5EFA\u7A7A\u767D\u6587\u6863" }] };
@@ -3447,8 +3356,7 @@ async function bringToFront() {
3447
3356
  if (!cad.connected) {
3448
3357
  await cad.connect();
3449
3358
  }
3450
- if (!cad.connected)
3451
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3359
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3452
3360
  const result = await cad.bringToFront();
3453
3361
  if (result) {
3454
3362
  return { content: [{ type: "text", text: "\u5DF2\u5C06 CAD \u7A97\u53E3\u5207\u6362\u5230\u524D\u53F0" }] };
@@ -3459,8 +3367,7 @@ async function installAtlisp() {
3459
3367
  if (!cad.connected) {
3460
3368
  await cad.connect();
3461
3369
  }
3462
- if (!cad.connected)
3463
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3370
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3464
3371
  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))))`;
3465
3372
  await cad.sendCommand(installCode + "\n");
3466
3373
  return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001 @lisp \u5B89\u88C5\u4EE3\u7801\u5230 CAD" }] };
@@ -3469,12 +3376,10 @@ async function listFunctionsInCad() {
3469
3376
  if (!cad.connected) {
3470
3377
  await cad.connect();
3471
3378
  }
3472
- if (!cad.connected)
3473
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3379
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3474
3380
  try {
3475
3381
  const result = await cad.sendCommandWithResult("(atoms-family 0)", null);
3476
- if (result)
3477
- return { content: [{ type: "text", text: result }] };
3382
+ if (result) return { content: [{ type: "text", text: result }] };
3478
3383
  return { content: [{ type: "text", text: "CAD \u51FD\u6570\u5217\u8868\u4E3A\u7A7A" }] };
3479
3384
  } catch (e) {
3480
3385
  return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
@@ -3531,8 +3436,7 @@ async function initAtlisp() {
3531
3436
  if (!cad.connected) {
3532
3437
  await cad.connect();
3533
3438
  }
3534
- if (!cad.connected)
3535
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3439
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3536
3440
  const code = `(if (null @::load-module)
3537
3441
  (progn
3538
3442
  (vl-load-com)
@@ -3574,15 +3478,12 @@ async function fetchPackages() {
3574
3478
  return cachedPackages || MOCK_PACKAGES;
3575
3479
  }
3576
3480
  function flattenPackages(data) {
3577
- if (Array.isArray(data))
3578
- return data;
3579
- if (data && Array.isArray(data.packages))
3580
- return data.packages;
3481
+ if (Array.isArray(data)) return data;
3482
+ if (data && Array.isArray(data.packages)) return data.packages;
3581
3483
  return [];
3582
3484
  }
3583
3485
  async function listPackages() {
3584
- if (!cad.connected)
3585
- await cad.connect();
3486
+ if (!cad.connected) await cad.connect();
3586
3487
  if (!cad.connected) {
3587
3488
  const data2 = await fetchPackages();
3588
3489
  const items2 = flattenPackages(data2);
@@ -3590,8 +3491,7 @@ async function listPackages() {
3590
3491
  return { content: [{ type: "text", text: text2 }] };
3591
3492
  }
3592
3493
  const result = await cad.sendCommandWithResult("(@::package-list-in-local)");
3593
- if (result && result !== "nil")
3594
- return { content: [{ type: "text", text: result }] };
3494
+ if (result && result !== "nil") return { content: [{ type: "text", text: result }] };
3595
3495
  const data = await fetchPackages();
3596
3496
  const items = flattenPackages(data);
3597
3497
  const text = items.length ? `\u4ECE\u6CE8\u518C\u8868\u83B7\u53D6\u7684 @lisp \u5305:
@@ -3611,12 +3511,10 @@ async function searchPackages(query) {
3611
3511
  for (const p of items) {
3612
3512
  const name = (p.name || "").toLowerCase();
3613
3513
  const desc = (p.description || "").toLowerCase();
3614
- if (name.includes(q) || desc.includes(q))
3615
- results.push(p);
3514
+ if (name.includes(q) || desc.includes(q)) results.push(p);
3616
3515
  }
3617
3516
  } else {
3618
- for (const p of items)
3619
- results.push(p);
3517
+ for (const p of items) results.push(p);
3620
3518
  }
3621
3519
  if (results.length === 0) {
3622
3520
  return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5305\u542B "${query}" \u7684\u5305` }] };
@@ -3705,8 +3603,7 @@ async function getFunctionUsage(funcName, packageName) {
3705
3603
  if (data) {
3706
3604
  const funcs = Object.values(data.all_functions || {});
3707
3605
  const func = funcs.find((f2) => f2.name === funcName || f2.name === `${packageName}:${funcName}`);
3708
- if (func)
3709
- results.push(func);
3606
+ if (func) results.push(func);
3710
3607
  }
3711
3608
  if (results.length === 0 && FUNCTIONS_DIR) {
3712
3609
  try {
@@ -3715,8 +3612,7 @@ async function getFunctionUsage(funcName, packageName) {
3715
3612
  const raw = fs6.readFileSync(path9.join(FUNCTIONS_DIR, file), "utf-8");
3716
3613
  const data2 = JSON.parse(raw);
3717
3614
  const func = data2.functions?.find((f2) => f2.name === funcName);
3718
- if (func)
3719
- results.push(func);
3615
+ if (func) results.push(func);
3720
3616
  }
3721
3617
  } catch (e) {
3722
3618
  log(`function-handlers: FUNCTIONS_DIR read error: ${e.message}`);
@@ -3786,8 +3682,7 @@ async function getEntity(handle) {
3786
3682
  if (!cad.connected) {
3787
3683
  await cad.connect();
3788
3684
  }
3789
- if (!cad.connected)
3790
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3685
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3791
3686
  const code = `(progn
3792
3687
  (vl-load-com)
3793
3688
  (if (setq ent (handent "${escapeLispString(handle)}"))
@@ -3819,8 +3714,7 @@ async function setEntityProperty(handle, property, value) {
3819
3714
  if (!cad.connected) {
3820
3715
  await cad.connect();
3821
3716
  }
3822
- if (!cad.connected)
3823
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3717
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3824
3718
  let propCode = "";
3825
3719
  switch (property) {
3826
3720
  case "layer":
@@ -3863,8 +3757,7 @@ async function deleteEntity(handle) {
3863
3757
  if (!cad.connected) {
3864
3758
  await cad.connect();
3865
3759
  }
3866
- if (!cad.connected)
3867
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3760
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3868
3761
  const code = `(progn
3869
3762
  (vl-load-com)
3870
3763
  (if (setq ent (handent "${escapeLispString(handle)}"))
@@ -3889,15 +3782,12 @@ async function selectEntities(filter) {
3889
3782
  if (!cad.connected) {
3890
3783
  await cad.connect();
3891
3784
  }
3892
- if (!cad.connected)
3893
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3785
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3894
3786
  let filterCode = "nil";
3895
3787
  if (filter && (filter.type || filter.layer)) {
3896
3788
  const items = [];
3897
- if (filter.type)
3898
- items.push(`'(0 . "${escapeLispString(filter.type)}")`);
3899
- if (filter.layer)
3900
- items.push(`'(8 . "${escapeLispString(filter.layer)}")`);
3789
+ if (filter.type) items.push(`'(0 . "${escapeLispString(filter.type)}")`);
3790
+ if (filter.layer) items.push(`'(8 . "${escapeLispString(filter.layer)}")`);
3901
3791
  filterCode = `(list ${items.join(" ")})`;
3902
3792
  }
3903
3793
  const code = `(progn
@@ -3930,8 +3820,7 @@ async function createLayer(name, color = 7, linetype = "Continuous") {
3930
3820
  if (!cad.connected) {
3931
3821
  await cad.connect();
3932
3822
  }
3933
- if (!cad.connected)
3934
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3823
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3935
3824
  const code = `(progn
3936
3825
  (vl-load-com)
3937
3826
  (if (not (tblsearch "LAYER" "${escapeLispString(name)}"))
@@ -3967,8 +3856,7 @@ async function deleteLayer(name) {
3967
3856
  if (!cad.connected) {
3968
3857
  await cad.connect();
3969
3858
  }
3970
- if (!cad.connected)
3971
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3859
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3972
3860
  const code = `(progn
3973
3861
  (vl-load-com)
3974
3862
  (cond
@@ -4002,8 +3890,7 @@ async function setLayerProperty(name, property, value) {
4002
3890
  if (!cad.connected) {
4003
3891
  await cad.connect();
4004
3892
  }
4005
- if (!cad.connected)
4006
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3893
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4007
3894
  let propCode = "";
4008
3895
  switch (property) {
4009
3896
  case "color":
@@ -4051,8 +3938,7 @@ async function setCurrentLayer(name) {
4051
3938
  if (!cad.connected) {
4052
3939
  await cad.connect();
4053
3940
  }
4054
- if (!cad.connected)
4055
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3941
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4056
3942
  const code = `(progn
4057
3943
  (vl-load-com)
4058
3944
  (if (tblsearch "LAYER" "${escapeLispString(name)}")
@@ -4080,8 +3966,7 @@ async function createBlock(name, entities) {
4080
3966
  if (!cad.connected) {
4081
3967
  await cad.connect();
4082
3968
  }
4083
- if (!cad.connected)
4084
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
3969
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4085
3970
  const code = `(progn
4086
3971
  (vl-load-com)
4087
3972
  (if (not (tblsearch "BLOCK" "${escapeLispString(name)}"))
@@ -4118,8 +4003,7 @@ async function insertBlock(blockName, point, scale = 1, rotation = 0) {
4118
4003
  if (!cad.connected) {
4119
4004
  await cad.connect();
4120
4005
  }
4121
- if (!cad.connected)
4122
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4006
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4123
4007
  const coords = Array.isArray(point) ? point : point.split(",").map((s) => parseFloat(s.trim()));
4124
4008
  if (coords.length < 2) {
4125
4009
  return { content: [{ type: "text", text: "\u63D2\u5165\u70B9\u683C\u5F0F\u9519\u8BEF\uFF0C\u9700\u8981 x,y \u6216 [x,y,z]" }], isError: true };
@@ -4149,8 +4033,7 @@ async function getBlocks() {
4149
4033
  if (!cad.connected) {
4150
4034
  await cad.connect();
4151
4035
  }
4152
- if (!cad.connected)
4153
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4036
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4154
4037
  const code = `(progn
4155
4038
  (vl-load-com)
4156
4039
  (setq blocks nil)
@@ -4173,8 +4056,7 @@ async function explodeBlock(handle) {
4173
4056
  if (!cad.connected) {
4174
4057
  await cad.connect();
4175
4058
  }
4176
- if (!cad.connected)
4177
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4059
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4178
4060
  const code = `(progn
4179
4061
  (vl-load-com)
4180
4062
  (if (setq ent (handent "${escapeLispString(handle)}"))
@@ -4210,8 +4092,7 @@ async function openDwg(filePath) {
4210
4092
  if (!cad.connected) {
4211
4093
  await cad.connect();
4212
4094
  }
4213
- if (!cad.connected)
4214
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4095
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4215
4096
  try {
4216
4097
  validateFilePath(filePath);
4217
4098
  } catch (e) {
@@ -4252,8 +4133,7 @@ async function saveDwg(filePath = null) {
4252
4133
  if (!cad.connected) {
4253
4134
  await cad.connect();
4254
4135
  }
4255
- if (!cad.connected)
4256
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4136
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4257
4137
  if (filePath) {
4258
4138
  try {
4259
4139
  validateFilePath(filePath);
@@ -4284,8 +4164,7 @@ async function exportPdf(outputPath, layout = "Model") {
4284
4164
  if (!cad.connected) {
4285
4165
  await cad.connect();
4286
4166
  }
4287
- if (!cad.connected)
4288
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4167
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4289
4168
  try {
4290
4169
  validateFilePath(outputPath);
4291
4170
  } catch (e) {
@@ -4317,8 +4196,7 @@ async function closeDwg(save = false) {
4317
4196
  if (!cad.connected) {
4318
4197
  await cad.connect();
4319
4198
  }
4320
- if (!cad.connected)
4321
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4199
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4322
4200
  const code = `(progn
4323
4201
  (vl-load-com)
4324
4202
  (if ${save ? "T" : "nil"}
@@ -4345,8 +4223,7 @@ async function createDimension(type, points, style = {}) {
4345
4223
  if (!cad.connected) {
4346
4224
  await cad.connect();
4347
4225
  }
4348
- if (!cad.connected)
4349
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4226
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4350
4227
  let dimCode = "";
4351
4228
  const validTypes = ["ALIGNED", "LINEAR", "ORDINATE", "RADIAL", "DIAMETER", "ANGULAR"];
4352
4229
  const dimType = (type || "ALIGNED").toUpperCase();
@@ -4388,8 +4265,7 @@ async function getDimensionValue(handle) {
4388
4265
  if (!cad.connected) {
4389
4266
  await cad.connect();
4390
4267
  }
4391
- if (!cad.connected)
4392
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4268
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4393
4269
  const code = `(progn
4394
4270
  (vl-load-com)
4395
4271
  (if (setq ent (handent "${escapeLispString(handle)}"))
@@ -4420,8 +4296,7 @@ async function createHatch(patternName, boundary, scale = 1, angle = 0) {
4420
4296
  if (!cad.connected) {
4421
4297
  await cad.connect();
4422
4298
  }
4423
- if (!cad.connected)
4424
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4299
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4425
4300
  const code = `(progn
4426
4301
  (vl-load-com)
4427
4302
  (command "._BHATCH" "p" "${escapeLispString(patternName)}" "s" "s" "sc" ${scale} "an" ${angle} "")
@@ -4441,17 +4316,12 @@ async function setHatchProperties(handle, props) {
4441
4316
  if (!cad.connected) {
4442
4317
  await cad.connect();
4443
4318
  }
4444
- if (!cad.connected)
4445
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4319
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4446
4320
  let propCode = "";
4447
- if (props.pattern)
4448
- propCode += `(command "._HATCHEDIT" "${escapeLispString(handle)}" "p" "${escapeLispString(props.pattern)}")`;
4449
- if (props.scale)
4450
- propCode += `(command "._HATCHEDIT" "${escapeLispString(handle)}" "s" ${parseFloat(props.scale) || 1})`;
4451
- if (props.angle)
4452
- propCode += `(command "._HATCHEDIT" "${escapeLispString(handle)}" "an" ${parseFloat(props.angle) || 0})`;
4453
- if (props.color)
4454
- propCode += `(command "._HATCHEDIT" "${escapeLispString(handle)}" "c" ${parseInt(props.color) || 256})`;
4321
+ if (props.pattern) propCode += `(command "._HATCHEDIT" "${escapeLispString(handle)}" "p" "${escapeLispString(props.pattern)}")`;
4322
+ if (props.scale) propCode += `(command "._HATCHEDIT" "${escapeLispString(handle)}" "s" ${parseFloat(props.scale) || 1})`;
4323
+ if (props.angle) propCode += `(command "._HATCHEDIT" "${escapeLispString(handle)}" "an" ${parseFloat(props.angle) || 0})`;
4324
+ if (props.color) propCode += `(command "._HATCHEDIT" "${escapeLispString(handle)}" "c" ${parseInt(props.color) || 256})`;
4455
4325
  const code = `(progn
4456
4326
  (vl-load-com)
4457
4327
  ${propCode}
@@ -4468,8 +4338,7 @@ async function getBlockAttributes(blockHandle) {
4468
4338
  if (!cad.connected) {
4469
4339
  await cad.connect();
4470
4340
  }
4471
- if (!cad.connected)
4472
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4341
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4473
4342
  const code = `(progn
4474
4343
  (vl-load-com)
4475
4344
  (if (setq ent (handent "${escapeLispString(blockHandle)}"))
@@ -4498,8 +4367,7 @@ async function setBlockAttribute(blockHandle, tag, value) {
4498
4367
  if (!cad.connected) {
4499
4368
  await cad.connect();
4500
4369
  }
4501
- if (!cad.connected)
4502
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4370
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4503
4371
  const code = `(progn
4504
4372
  (vl-load-com)
4505
4373
  (if (setq ent (handent "${escapeLispString(blockHandle)}"))
@@ -4535,8 +4403,7 @@ async function zoomToExtents() {
4535
4403
  if (!cad.connected) {
4536
4404
  await cad.connect();
4537
4405
  }
4538
- if (!cad.connected)
4539
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4406
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4540
4407
  const code = `(progn
4541
4408
  (vl-load-com)
4542
4409
  (command "._ZOOM" "E")
@@ -4553,8 +4420,7 @@ async function zoomToWindow(p1, p2) {
4553
4420
  if (!cad.connected) {
4554
4421
  await cad.connect();
4555
4422
  }
4556
- if (!cad.connected)
4557
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4423
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4558
4424
  const code = `(command "._ZOOM" "W" (list ${toSafePoint(p1)}) (list ${toSafePoint(p2)}))`;
4559
4425
  try {
4560
4426
  await cad.sendCommand(code + "\n");
@@ -4567,8 +4433,7 @@ async function createNamedView(viewName, center = null) {
4567
4433
  if (!cad.connected) {
4568
4434
  await cad.connect();
4569
4435
  }
4570
- if (!cad.connected)
4571
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4436
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4572
4437
  const code = center ? `(command ".-VIEW" "S" "${escapeLispString(viewName)}" "C" (list ${toSafePoint(center)}))` : `(command ".-VIEW" "S" "${escapeLispString(viewName)}")`;
4573
4438
  try {
4574
4439
  await cad.sendCommand(code + "\n");
@@ -4581,8 +4446,7 @@ async function restoreNamedView(viewName) {
4581
4446
  if (!cad.connected) {
4582
4447
  await cad.connect();
4583
4448
  }
4584
- if (!cad.connected)
4585
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4449
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4586
4450
  const code = `(command ".-VIEW" "R" "${escapeLispString(viewName)}")`;
4587
4451
  try {
4588
4452
  await cad.sendCommand(code + "\n");
@@ -4595,8 +4459,7 @@ async function listNamedViews() {
4595
4459
  if (!cad.connected) {
4596
4460
  await cad.connect();
4597
4461
  }
4598
- if (!cad.connected)
4599
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4462
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4600
4463
  const code = `(progn
4601
4464
  (vl-load-com)
4602
4465
  (setq views nil)
@@ -4616,8 +4479,7 @@ async function exportDxf(outputPath, version2 = "R2018") {
4616
4479
  if (!cad.connected) {
4617
4480
  await cad.connect();
4618
4481
  }
4619
- if (!cad.connected)
4620
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4482
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4621
4483
  const versionMap = {
4622
4484
  "R2018": "AC1027",
4623
4485
  "R2015": "AC1024",
@@ -4647,8 +4509,7 @@ async function exportDwf(outputPath) {
4647
4509
  if (!cad.connected) {
4648
4510
  await cad.connect();
4649
4511
  }
4650
- if (!cad.connected)
4651
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4512
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4652
4513
  const code = `(progn
4653
4514
  (vl-load-com)
4654
4515
  (vla-export (vla-get-activedocument (vlax-get-acad-object)) "${escapeLispString(outputPath)}" "dwf")
@@ -4668,8 +4529,7 @@ async function batchSetLayer(handles, layerName) {
4668
4529
  if (!cad.connected) {
4669
4530
  await cad.connect();
4670
4531
  }
4671
- if (!cad.connected)
4672
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4532
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4673
4533
  if (!Array.isArray(handles) || handles.length === 0) {
4674
4534
  return { content: [{ type: "text", text: "\u53E5\u67C4\u5217\u8868\u4E3A\u7A7A" }], isError: true };
4675
4535
  }
@@ -4699,8 +4559,7 @@ async function createUcs(name, origin = "0,0,0", xAxis = "1,0,0", yAxis = "0,1,0
4699
4559
  if (!cad.connected) {
4700
4560
  await cad.connect();
4701
4561
  }
4702
- if (!cad.connected)
4703
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4562
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4704
4563
  const code = `(progn
4705
4564
  (vl-load-com)
4706
4565
  (if (not (tblsearch "UCS" "${escapeLispString(name)}"))
@@ -4731,8 +4590,7 @@ async function setUcs(name) {
4731
4590
  if (!cad.connected) {
4732
4591
  await cad.connect();
4733
4592
  }
4734
- if (!cad.connected)
4735
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4593
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4736
4594
  const code = `(progn
4737
4595
  (vl-load-com)
4738
4596
  (if (tblsearch "UCS" "${escapeLispString(name)}")
@@ -4757,8 +4615,7 @@ async function listUcs() {
4757
4615
  if (!cad.connected) {
4758
4616
  await cad.connect();
4759
4617
  }
4760
- if (!cad.connected)
4761
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4618
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4762
4619
  const code = `(progn
4763
4620
  (vl-load-com)
4764
4621
  (setq ucsList nil)
@@ -4781,8 +4638,7 @@ async function deleteUcs(name) {
4781
4638
  if (!cad.connected) {
4782
4639
  await cad.connect();
4783
4640
  }
4784
- if (!cad.connected)
4785
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4641
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4786
4642
  const code = `(progn
4787
4643
  (vl-load-com)
4788
4644
  (if (tblsearch "UCS" "${escapeLispString(name)}")
@@ -4807,8 +4663,7 @@ async function getCurrentUcs() {
4807
4663
  if (!cad.connected) {
4808
4664
  await cad.connect();
4809
4665
  }
4810
- if (!cad.connected)
4811
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4666
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4812
4667
  const code = `(progn
4813
4668
  (vl-load-com)
4814
4669
  (vla-get-activeutilities (vla-get-document (vla-get-application (vlax-get-acad-object))))
@@ -4825,8 +4680,7 @@ async function createLayout(name) {
4825
4680
  if (!cad.connected) {
4826
4681
  await cad.connect();
4827
4682
  }
4828
- if (!cad.connected)
4829
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4683
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4830
4684
  const code = `(progn
4831
4685
  (vl-load-com)
4832
4686
  (if (not (tblsearch "LAYOUT" "${escapeLispString(name)}"))
@@ -4854,8 +4708,7 @@ async function setLayout(name) {
4854
4708
  if (!cad.connected) {
4855
4709
  await cad.connect();
4856
4710
  }
4857
- if (!cad.connected)
4858
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4711
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4859
4712
  const code = `(progn
4860
4713
  (vl-load-com)
4861
4714
  (vlax-for layout (vla-get-layouts (vla-get-activedocument (vla-get-application (vlax-get-acad-object))))
@@ -4885,8 +4738,7 @@ async function listLayouts() {
4885
4738
  if (!cad.connected) {
4886
4739
  await cad.connect();
4887
4740
  }
4888
- if (!cad.connected)
4889
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4741
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4890
4742
  const code = `(progn
4891
4743
  (vl-load-com)
4892
4744
  (setq layouts nil)
@@ -4909,8 +4761,7 @@ async function deleteLayout(name) {
4909
4761
  if (!cad.connected) {
4910
4762
  await cad.connect();
4911
4763
  }
4912
- if (!cad.connected)
4913
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4764
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4914
4765
  if (name === "Model" || name === "\u6A21\u578B") {
4915
4766
  return { content: [{ type: "text", text: "\u65E0\u6CD5\u5220\u9664\u6A21\u578B\u7A7A\u95F4" }], isError: true };
4916
4767
  }
@@ -4938,8 +4789,7 @@ async function getCurrentLayout() {
4938
4789
  if (!cad.connected) {
4939
4790
  await cad.connect();
4940
4791
  }
4941
- if (!cad.connected)
4942
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4792
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4943
4793
  const code = `(vl-prin1-to-string (getvar "CTAB"))`;
4944
4794
  try {
4945
4795
  const result = await cad.sendCommandWithResult(code);
@@ -4952,8 +4802,7 @@ async function renameLayout(oldName, newName) {
4952
4802
  if (!cad.connected) {
4953
4803
  await cad.connect();
4954
4804
  }
4955
- if (!cad.connected)
4956
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4805
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4957
4806
  const code = `(progn
4958
4807
  (vl-load-com)
4959
4808
  (if (tblsearch "LAYOUT" "${escapeLispString(oldName)}")
@@ -4985,8 +4834,7 @@ async function plotToPdf(outputPath, layout = "Model", style = {}) {
4985
4834
  if (!cad.connected) {
4986
4835
  await cad.connect();
4987
4836
  }
4988
- if (!cad.connected)
4989
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4837
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4990
4838
  const paperSize = style.paperSize || "A4";
4991
4839
  const code = `(progn
4992
4840
  (vl-load-com)
@@ -5016,8 +4864,7 @@ async function plotToPrinter(printerName, layout = "Model") {
5016
4864
  if (!cad.connected) {
5017
4865
  await cad.connect();
5018
4866
  }
5019
- if (!cad.connected)
5020
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4867
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5021
4868
  const code = `(progn
5022
4869
  (vl-load-com)
5023
4870
  (setq doc (vla-get-activedocument (vlax-get-acad-object)))
@@ -5043,8 +4890,7 @@ async function createGroup(name, handles) {
5043
4890
  if (!cad.connected) {
5044
4891
  await cad.connect();
5045
4892
  }
5046
- if (!cad.connected)
5047
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4893
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5048
4894
  if (!Array.isArray(handles) || handles.length === 0) {
5049
4895
  return { content: [{ type: "text", text: "\u53E5\u67C4\u5217\u8868\u4E3A\u7A7A" }], isError: true };
5050
4896
  }
@@ -5070,8 +4916,7 @@ async function deleteGroup(name) {
5070
4916
  if (!cad.connected) {
5071
4917
  await cad.connect();
5072
4918
  }
5073
- if (!cad.connected)
5074
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4919
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5075
4920
  const code = `(progn
5076
4921
  (vl-load-com)
5077
4922
  (if (tblsearch "GROUP" "${escapeLispString(name)}")
@@ -5096,8 +4941,7 @@ async function listGroups() {
5096
4941
  if (!cad.connected) {
5097
4942
  await cad.connect();
5098
4943
  }
5099
- if (!cad.connected)
5100
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4944
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5101
4945
  const code = `(progn
5102
4946
  (vl-load-com)
5103
4947
  (setq groups nil)
@@ -5117,8 +4961,7 @@ async function getGroupEntities(groupName) {
5117
4961
  if (!cad.connected) {
5118
4962
  await cad.connect();
5119
4963
  }
5120
- if (!cad.connected)
5121
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
4964
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5122
4965
  const code = `(progn
5123
4966
  (vl-load-com)
5124
4967
  (if (tblsearch "GROUP" "${escapeLispString(groupName)}")
@@ -5156,8 +4999,7 @@ async function measureDistance(p1, p2) {
5156
4999
  if (!cad.connected) {
5157
5000
  await cad.connect();
5158
5001
  }
5159
- if (!cad.connected)
5160
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5002
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5161
5003
  const code = `(progn
5162
5004
  (vl-load-com)
5163
5005
  (setq pt1 (list ${toSafePoint3(p1)}) pt2 (list ${toSafePoint3(p2)}))
@@ -5181,8 +5023,7 @@ async function measureArea(points) {
5181
5023
  if (!cad.connected) {
5182
5024
  await cad.connect();
5183
5025
  }
5184
- if (!cad.connected)
5185
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5026
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5186
5027
  const pts = Array.isArray(points) ? points : points.split(/[\s,]+/).filter(Boolean);
5187
5028
  if (pts.length < 3) {
5188
5029
  return { content: [{ type: "text", text: "\u81F3\u5C11\u9700\u8981 3 \u4E2A\u70B9" }], isError: true };
@@ -5219,8 +5060,7 @@ async function getEntityInfo(handle) {
5219
5060
  if (!cad.connected) {
5220
5061
  await cad.connect();
5221
5062
  }
5222
- if (!cad.connected)
5223
- return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5063
+ if (!cad.connected) return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
5224
5064
  const code = `(progn
5225
5065
  (vl-load-com)
5226
5066
  (if (setq ent (handent "${escapeLispString(handle)}"))
@@ -5260,8 +5100,7 @@ function parseHandleList(handles) {
5260
5100
  handles = handles.split(",").map((h) => h.trim());
5261
5101
  }
5262
5102
  }
5263
- if (!Array.isArray(handles))
5264
- handles = [handles];
5103
+ if (!Array.isArray(handles)) handles = [handles];
5265
5104
  return handles;
5266
5105
  }
5267
5106
  async function batchRename(handles, newNameTemplate, startNum = 1) {
@@ -5635,8 +5474,7 @@ async function copyXdata(sourceHandle, targetHandle, appName = null) {
5635
5474
  const xdataResult = await getXdata(sourceHandle, appName);
5636
5475
  if (xdataResult.content?.[0]) {
5637
5476
  const parsed = JSON.parse(xdataResult.content[0].text);
5638
- if (parsed.xdata)
5639
- return await setXdata(targetHandle, appName, parsed.xdata);
5477
+ if (parsed.xdata) return await setXdata(targetHandle, appName, parsed.xdata);
5640
5478
  }
5641
5479
  return mcpError("\u6E90\u5B9E\u4F53\u672A\u627E\u5230\u6269\u5C55\u6570\u636E");
5642
5480
  } else {
@@ -5871,10 +5709,8 @@ async function createSheetSetArchive(sheetSetName, archivePath) {
5871
5709
  // src/handlers/3d-handlers.js
5872
5710
  init_cad();
5873
5711
  function parsePoint(point) {
5874
- if (Array.isArray(point))
5875
- return point.join(" ");
5876
- if (typeof point === "string")
5877
- return point;
5712
+ if (Array.isArray(point)) return point.join(" ");
5713
+ if (typeof point === "string") return point;
5878
5714
  return "0,0,0";
5879
5715
  }
5880
5716
  async function createBox(center, length, width, height) {
@@ -8346,8 +8182,7 @@ function validateToolArgs(name, args) {
8346
8182
  const baseType = type.replace("?", "");
8347
8183
  const val = args[key];
8348
8184
  if (val === void 0 || val === null) {
8349
- if (isOptional)
8350
- continue;
8185
+ if (isOptional) continue;
8351
8186
  throw new Error(`Missing required argument: ${key}`);
8352
8187
  }
8353
8188
  const actualType = typeof args[key];
@@ -8392,8 +8227,7 @@ ${CAD_PLATFORMS.join("\n")}
8392
8227
  },
8393
8228
  import_funlib: async (a) => {
8394
8229
  const data = await loadAtlibFunctionLib();
8395
- if (!data)
8396
- return { content: [{ type: "text", text: "\u52A0\u8F7D\u51FD\u6570\u5E93\u5931\u8D25" }], isError: true };
8230
+ if (!data) return { content: [{ type: "text", text: "\u52A0\u8F7D\u51FD\u6570\u5E93\u5931\u8D25" }], isError: true };
8397
8231
  if (a.format === "list") {
8398
8232
  const items = Object.values(data.all_functions || {}).map((f) => `${f.name}: ${f.description || ""}`);
8399
8233
  return { content: [{ type: "text", text: items.join("\n") }] };
@@ -8603,8 +8437,7 @@ function notifyResourceChanges(toolName) {
8603
8437
  }
8604
8438
  async function handleToolCall(name, args) {
8605
8439
  const handler = TOOL_HANDLERS[name];
8606
- if (!handler)
8607
- return { content: [{ type: "text", text: `\u672A\u77E5\u5DE5\u5177: ${name}` }], isError: true };
8440
+ if (!handler) return { content: [{ type: "text", text: `\u672A\u77E5\u5DE5\u5177: ${name}` }], isError: true };
8608
8441
  try {
8609
8442
  validateToolArgs(name, args || {});
8610
8443
  const result = await handler(args || {});
@@ -8665,12 +8498,10 @@ var RateLimiter = class {
8665
8498
  this.keyLimits = /* @__PURE__ */ new Map();
8666
8499
  }
8667
8500
  getKeyLimit(apiKey2) {
8668
- if (!apiKey2)
8669
- return this.defaultLimit;
8501
+ if (!apiKey2) return this.defaultLimit;
8670
8502
  if (config_default.apiKeys && config_default.apiKeys.length > 0) {
8671
8503
  const found = config_default.apiKeys.find((k) => k.key === apiKey2);
8672
- if (found)
8673
- return found.limit;
8504
+ if (found) return found.limit;
8674
8505
  }
8675
8506
  if (config_default.apiKey && apiKey2 === config_default.apiKey) {
8676
8507
  return config_default.apiKeyRateLimit || 1e3;
@@ -8678,12 +8509,10 @@ var RateLimiter = class {
8678
8509
  return this.defaultLimit;
8679
8510
  }
8680
8511
  getKeyInfo(apiKey2) {
8681
- if (!apiKey2)
8682
- return { name: "anonymous", limit: this.defaultLimit };
8512
+ if (!apiKey2) return { name: "anonymous", limit: this.defaultLimit };
8683
8513
  if (config_default.apiKeys && config_default.apiKeys.length > 0) {
8684
8514
  const found = config_default.apiKeys.find((k) => k.key === apiKey2);
8685
- if (found)
8686
- return { name: found.name || apiKey2, limit: found.limit };
8515
+ if (found) return { name: found.name || apiKey2, limit: found.limit };
8687
8516
  }
8688
8517
  if (config_default.apiKey && apiKey2 === config_default.apiKey) {
8689
8518
  return { name: "admin", limit: config_default.apiKeyRateLimit || 1e3 };
@@ -8779,8 +8608,7 @@ var JSON_CONTENT_TYPES = ["application/json", "application/json-rpc", "applicati
8779
8608
  function createJsonBodyParser() {
8780
8609
  return async (req, res, next) => {
8781
8610
  const ct = (req.headers["content-type"] || "").toLowerCase();
8782
- if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t)))
8783
- return next();
8611
+ if (!JSON_CONTENT_TYPES.some((t) => ct.startsWith(t))) return next();
8784
8612
  try {
8785
8613
  const chunks = [];
8786
8614
  for await (const chunk of req) {
@@ -8813,11 +8641,9 @@ function createAuthMiddleware() {
8813
8641
  const PUBLIC_PATHS = ["/health"];
8814
8642
  return (req, res, next) => {
8815
8643
  if (apiKey) {
8816
- if (PUBLIC_PATHS.includes(req.path))
8817
- return next();
8644
+ if (PUBLIC_PATHS.includes(req.path)) return next();
8818
8645
  const auth = req.get("Authorization");
8819
- if (auth === `Bearer ${apiKey}`)
8820
- return next();
8646
+ if (auth === `Bearer ${apiKey}`) return next();
8821
8647
  return res.status(401).json({ error: "Unauthorized" });
8822
8648
  }
8823
8649
  next();
@@ -8825,16 +8651,14 @@ function createAuthMiddleware() {
8825
8651
  }
8826
8652
  function createCorsMiddleware() {
8827
8653
  return (req, res, next) => {
8828
- if (!enableCors)
8829
- return next();
8654
+ if (!enableCors) return next();
8830
8655
  res.setHeader("Access-Control-Allow-Origin", corsOrigin);
8831
8656
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, CONNECT");
8832
8657
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, mcp-session-id, last-event-id");
8833
8658
  res.setHeader("Access-Control-Expose-Headers", "mcp-session-id, content-type, x-accel-buffering");
8834
8659
  res.setHeader("Access-Control-Max-Age", "86400");
8835
8660
  res.setHeader("Vary", "Accept");
8836
- if (req.method === "OPTIONS")
8837
- return res.status(204).end();
8661
+ if (req.method === "OPTIONS") return res.status(204).end();
8838
8662
  next();
8839
8663
  };
8840
8664
  }
@@ -9251,8 +9075,7 @@ For more info: https://atlisp.cn
9251
9075
  }
9252
9076
  }
9253
9077
  }
9254
- if (config_default.apiKey)
9255
- log("API Key authentication enabled");
9078
+ if (config_default.apiKey) log("API Key authentication enabled");
9256
9079
  async function initCadConnection() {
9257
9080
  log("Attempting to connect to CAD on startup...");
9258
9081
  try {
@@ -9317,10 +9140,8 @@ async function startServer() {
9317
9140
  await cad.disconnect();
9318
9141
  closeLog();
9319
9142
  httpServer.close(() => {
9320
- if (httpsServer)
9321
- httpsServer.close(() => process.exit(0));
9322
- else
9323
- process.exit(0);
9143
+ if (httpsServer) httpsServer.close(() => process.exit(0));
9144
+ else process.exit(0);
9324
9145
  });
9325
9146
  setTimeout(() => process.exit(1), 5e3);
9326
9147
  }
@@ -9328,6 +9149,22 @@ async function startServer() {
9328
9149
  process.on("SIGTERM", () => shutdown("SIGTERM"));
9329
9150
  }
9330
9151
  }
9152
+ onDocumentChanged((info) => {
9153
+ const uris = [
9154
+ "atlisp://dwg/name",
9155
+ "atlisp://dwg/path",
9156
+ "atlisp://cad/dwgs",
9157
+ "atlisp://dwg/tbl",
9158
+ "atlisp://dwg/entities",
9159
+ "atlisp://dwg/block-refs",
9160
+ "atlisp://dwg/text-content",
9161
+ "atlisp://dwg/groups"
9162
+ ];
9163
+ for (const uri of uris) {
9164
+ clearCache(uri);
9165
+ notify(uri, { docName: info.docName, docPath: info.docPath });
9166
+ }
9167
+ });
9331
9168
  if (!process.env.VITEST) {
9332
9169
  await startServer();
9333
9170
  }