@atlisp/mcp 1.3.5 → 1.3.8

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.
@@ -454,16 +454,18 @@ async function evalLisp(code, withResult = false, encoding = null) {
454
454
  if (!cad.connected) {
455
455
  return { content: [{ type: "text", text: "\u672A\u8FDE\u63A5 CAD" }], isError: true };
456
456
  }
457
+ const trimmed = (code || "").trim();
458
+ if (!trimmed) return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
457
459
  try {
458
460
  if (withResult) {
459
- const result = await cad.sendCommandWithResult(code, encoding);
461
+ const result = await cad.sendCommandWithResult(trimmed, encoding);
460
462
  if (result !== null) {
461
463
  return { content: [{ type: "text", text: result }] };
462
464
  }
463
465
  return { content: [{ type: "text", text: "\u6267\u884C\u5931\u8D25\u6216\u65E0\u8FD4\u56DE\u503C" }], isError: true };
464
466
  } else {
465
- await cad.sendCommand(code + "\n");
466
- return { content: [{ type: "text", text: `\u5DF2\u53D1\u9001\u547D\u4EE4: ${code}` }] };
467
+ await cad.sendCommand(trimmed + "\n");
468
+ return { content: [{ type: "text", text: `\u5DF2\u53D1\u9001\u547D\u4EE4` }] };
467
469
  }
468
470
  } catch (e) {
469
471
  return { content: [{ type: "text", text: `\u9519\u8BEF: ${e.message}` }], isError: true };
@@ -479,8 +481,10 @@ async function getCadInfo() {
479
481
  }
480
482
  async function atCommand(command) {
481
483
  if (!cad.connected) return { content: [{ type: "text", text: "\u8BF7\u5148\u8FDE\u63A5 CAD" }], isError: true };
482
- await cad.sendCommand(command + "\n");
483
- return { content: [{ type: "text", text: `\u5DF2\u53D1\u9001\u547D\u4EE4: ${command}` }] };
484
+ const trimmed = (command || "").trim();
485
+ if (!trimmed) return { content: [{ type: "text", text: "\u547D\u4EE4\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001" }] };
486
+ await cad.sendCommand(trimmed + "\n");
487
+ return { content: [{ type: "text", text: "\u5DF2\u53D1\u9001\u547D\u4EE4" }] };
484
488
  }
485
489
  async function newDocument() {
486
490
  if (!cad.connected) {
@@ -726,6 +730,17 @@ function getCached(key) {
726
730
  function setCache(key, data) {
727
731
  resourceCache.set(key, { data, timestamp: Date.now() });
728
732
  }
733
+ function clearCache(uri) {
734
+ if (uri) {
735
+ for (const key of resourceCache.keys()) {
736
+ if (key.startsWith(uri.split("://")[1]?.split("/")[0] + ":")) {
737
+ resourceCache.delete(key);
738
+ }
739
+ }
740
+ } else {
741
+ resourceCache.clear();
742
+ }
743
+ }
729
744
  function parseLispList(str) {
730
745
  if (!str || typeof str !== "string") return null;
731
746
  const trimmed = str.trim();
@@ -1011,17 +1026,60 @@ async function getDwgPath() {
1011
1026
  }
1012
1027
  }
1013
1028
  async function getPackages(filterName = null) {
1014
- const packages = MOCK_PACKAGES.map((p) => ({
1015
- name: p.name,
1016
- version: p.version,
1017
- description: p.description,
1018
- loaded: true
1019
- }));
1020
- if (filterName) {
1021
- const pkg = packages.find((p) => p.name === filterName);
1022
- return pkg ? [pkg] : [];
1029
+ const cacheKey = filterName ? `packages:${filterName}` : "packages:all";
1030
+ const cached = getCached(cacheKey);
1031
+ if (cached) return cached;
1032
+ if (!cad.connected) await cad.connect();
1033
+ if (!cad.connected) return [];
1034
+ try {
1035
+ const code = `(mapcar 'cdr @::*local-pkgs*)`;
1036
+ const result = await cad.sendCommandWithResult(code);
1037
+ if (!result || result === "" || result === "nil") {
1038
+ setCache(cacheKey, []);
1039
+ return [];
1040
+ }
1041
+ let raw = [];
1042
+ try {
1043
+ raw = JSON.parse(result);
1044
+ } catch {
1045
+ raw = parseLispList(result) || [];
1046
+ }
1047
+ if (!Array.isArray(raw)) raw = [];
1048
+ const packages = raw.map((item) => {
1049
+ if (Array.isArray(item)) {
1050
+ const pkg = { name: "", version: "0.0.0", description: "", loaded: true };
1051
+ for (const entry of item) {
1052
+ if (entry && typeof entry === "object" && !Array.isArray(entry)) {
1053
+ const [[key, val]] = Object.entries(entry);
1054
+ const k = String(key);
1055
+ const v = String(val);
1056
+ if (k === ":NAME") pkg.name = v;
1057
+ else if (k === ":VERSION") pkg.version = v;
1058
+ else if (k === ":DESCRIPTION") pkg.description = v;
1059
+ else if (k === ":FULL-NAME") pkg.fullName = v;
1060
+ else if (k === ":AUTHOR") pkg.author = v;
1061
+ else if (k === ":CATEGORY") pkg.category = v;
1062
+ else if (k === ":URL") pkg.url = v;
1063
+ }
1064
+ }
1065
+ return pkg;
1066
+ }
1067
+ if (typeof item === "string" || typeof item === "number") {
1068
+ return { name: String(item), version: "0.0.0", loaded: true };
1069
+ }
1070
+ return null;
1071
+ }).filter(Boolean);
1072
+ if (filterName) {
1073
+ const filtered = packages.filter((p) => p.name === filterName);
1074
+ setCache(cacheKey, filtered);
1075
+ return filtered;
1076
+ }
1077
+ setCache(cacheKey, packages);
1078
+ return packages;
1079
+ } catch (e) {
1080
+ setCache(cacheKey, []);
1081
+ return [];
1023
1082
  }
1024
- return packages;
1025
1083
  }
1026
1084
  function getPlatforms() {
1027
1085
  return CAD_PLATFORMS.map((name) => ({
@@ -1075,6 +1133,92 @@ var PROMPTS = [
1075
1133
  arguments: [
1076
1134
  { name: "format", description: "\u5BFC\u51FA\u683C\u5F0F (json/list)", required: false }
1077
1135
  ]
1136
+ },
1137
+ {
1138
+ name: "manage-layers",
1139
+ description: "\u56FE\u5C42\u7BA1\u7406\uFF1A\u521B\u5EFA\u3001\u51BB\u7ED3\u3001\u9501\u5B9A\u3001\u5220\u9664\u56FE\u5C42",
1140
+ arguments: [
1141
+ { name: "action", description: "\u64CD\u4F5C\u7C7B\u578B (list/freeze/lock/off/make/delete)", required: true },
1142
+ { name: "layers", description: "\u56FE\u5C42\u540D\uFF0C\u591A\u4E2A\u7528\u9017\u53F7\u5206\u9694", required: false },
1143
+ { name: "color", description: '\u56FE\u5C42\u989C\u8272 (ACI\u53F7\u6216RGB\u5982 "1,2,3")', required: false }
1144
+ ]
1145
+ },
1146
+ {
1147
+ name: "manage-blocks",
1148
+ description: "\u5757\u64CD\u4F5C\uFF1A\u63D2\u5165\u5757\u3001\u5217\u51FA\u5757\u3001\u83B7\u53D6/\u8BBE\u7F6E\u5C5E\u6027",
1149
+ arguments: [
1150
+ { name: "action", description: "\u64CD\u4F5C\u7C7B\u578B (list/insert/attributes/dynprops)", required: true },
1151
+ { name: "blockName", description: "\u5757\u540D", required: false },
1152
+ { name: "insertPoint", description: '\u63D2\u5165\u70B9 "x,y"', required: false },
1153
+ { name: "scale", description: "\u7F29\u653E\u6BD4\u4F8B", required: false }
1154
+ ]
1155
+ },
1156
+ {
1157
+ name: "curve-analysis",
1158
+ description: "\u66F2\u7EBF\u5206\u6790\uFF1A\u4EA4\u70B9\u3001\u6700\u8FD1\u70B9\u3001\u5B50\u6BB5\u3001\u7F13\u51B2\u533A",
1159
+ arguments: [
1160
+ { name: "action", description: "\u64CD\u4F5C (inters/subsegments/closestpoint/join)", required: true },
1161
+ { name: "distance", description: "\u8FDE\u63A5\u5BB9\u5DEE/\u504F\u79FB\u8DDD\u79BB", required: false }
1162
+ ]
1163
+ },
1164
+ {
1165
+ name: "geometry-calc",
1166
+ description: "\u51E0\u4F55\u8BA1\u7B97\uFF1A\u51F8\u5305\u3001\u70B9\u5230\u7EBF\u8DDD\u79BB\u3001\u9762\u5185\u6D4B\u8BD5\u3001\u53D8\u6362",
1167
+ arguments: [
1168
+ { name: "action", description: "\u64CD\u4F5C (convexhull/dist-point-line/in-curve-p/transform/centroid)", required: true },
1169
+ { name: "points", description: '\u70B9\u96C6 "x1,y1;x2,y2;..."', required: false }
1170
+ ]
1171
+ },
1172
+ {
1173
+ name: "text-process",
1174
+ description: "\u6587\u672C\u5904\u7406\uFF1AMTEXT\u89E3\u6790\u3001Markdown\u8F6CMTEXT\u3001\u53BB\u683C\u5F0F",
1175
+ arguments: [
1176
+ { name: "action", description: "\u64CD\u4F5C (parse-mtext/remove-fmt/from-markdown/mtext2text)", required: true },
1177
+ { name: "markdown", description: "Markdown\u6587\u672C\uFF08from-markdown\u64CD\u4F5C\u65F6\u7528\uFF09", required: false }
1178
+ ]
1179
+ },
1180
+ {
1181
+ name: "pickset-filter",
1182
+ description: "\u9009\u62E9\u96C6\u64CD\u4F5C\uFF1A\u8FC7\u6EE4\u3001\u8F6C\u6362\u3001\u6279\u91CF\u64CD\u4F5C",
1183
+ arguments: [
1184
+ { name: "action", description: "\u64CD\u4F5C (by-layer/by-type/by-box/erase/zoom)", required: true },
1185
+ { name: "dxfType", description: 'DXF\u7C7B\u578B "LINE, CIRCLE, LWPOLYLINE, INSERT, TEXT"', required: false },
1186
+ { name: "layerName", description: "\u56FE\u5C42\u540D", required: false }
1187
+ ]
1188
+ },
1189
+ {
1190
+ name: "color-convert",
1191
+ description: "\u989C\u8272\u8F6C\u6362\uFF1AACI/RGB/TrueColor/CSS\u4E92\u8F6C",
1192
+ arguments: [
1193
+ { name: "action", description: "\u64CD\u4F5C (aci2rgb/rgb2css/truecolor2rgb/rgb2truecolor)", required: true },
1194
+ { name: "value", description: "\u989C\u8272\u503C", required: true }
1195
+ ]
1196
+ },
1197
+ {
1198
+ name: "json-exchange",
1199
+ description: "JSON\u6570\u636E\u4EA4\u6362\uFF1A\u4ECE\u5B57\u7B26\u4E32\u89E3\u6790JSON alist\uFF0C\u4ECEalist\u751F\u6210JSON",
1200
+ arguments: [
1201
+ { name: "action", description: "\u64CD\u4F5C (encode/decode)", required: true },
1202
+ { name: "data", description: "JSON\u5B57\u7B26\u4E32\u6216Lisp alist\u6587\u672C", required: true }
1203
+ ]
1204
+ },
1205
+ {
1206
+ name: "excel-report",
1207
+ description: "Excel\u62A5\u8868\uFF1A\u5BFC\u51FACAD\u5B9E\u4F53\u6570\u636E\u5230Excel",
1208
+ arguments: [
1209
+ { name: "visible", description: "\u662F\u5426\u663E\u793AExcel\u7A97\u53E3 (true/false)", required: false },
1210
+ { name: "savePath", description: "\u4FDD\u5B58\u8DEF\u5F84\uFF0C\u4E0D\u586B\u5219\u4E0D\u4FDD\u5B58", required: false }
1211
+ ]
1212
+ },
1213
+ {
1214
+ name: "string-process",
1215
+ description: "\u5B57\u7B26\u4E32\u5904\u7406\uFF1A\u683C\u5F0F\u5316\u3001\u62C6\u5206\u3001\u66FF\u6362\u3001\u6B63\u5219",
1216
+ arguments: [
1217
+ { name: "action", description: "\u64CD\u4F5C (format/split/subst-all/regexp/trim/number2chinese)", required: true },
1218
+ { name: "input", description: "\u8F93\u5165\u5B57\u7B26\u4E32", required: true },
1219
+ { name: "arg1", description: "\u53C2\u65701\uFF08\u683C\u5F0F\u53C2\u6570/\u5206\u9694\u7B26/\u65E7\u4E32\uFF09", required: false },
1220
+ { name: "arg2", description: "\u53C2\u65702\uFF08\u65B0\u4E32/\u6B63\u5219\u6A21\u5F0F\uFF09", required: false }
1221
+ ]
1078
1222
  }
1079
1223
  ];
1080
1224
  async function listPrompts() {
@@ -1094,6 +1238,26 @@ async function getPrompt(name, arguments_ = {}) {
1094
1238
  return generateDimensionPrompt(arguments_);
1095
1239
  case "export-entities":
1096
1240
  return generateExportPrompt(arguments_);
1241
+ case "manage-layers":
1242
+ return generateManageLayersPrompt(arguments_);
1243
+ case "manage-blocks":
1244
+ return generateManageBlocksPrompt(arguments_);
1245
+ case "curve-analysis":
1246
+ return generateCurveAnalysisPrompt(arguments_);
1247
+ case "geometry-calc":
1248
+ return generateGeometryCalcPrompt(arguments_);
1249
+ case "text-process":
1250
+ return generateTextProcessPrompt(arguments_);
1251
+ case "pickset-filter":
1252
+ return generatePicksetFilterPrompt(arguments_);
1253
+ case "color-convert":
1254
+ return generateColorConvertPrompt(arguments_);
1255
+ case "json-exchange":
1256
+ return generateJsonExchangePrompt(arguments_);
1257
+ case "excel-report":
1258
+ return generateExcelReportPrompt(arguments_);
1259
+ case "string-process":
1260
+ return generateStringProcessPrompt(arguments_);
1097
1261
  default:
1098
1262
  throw new Error(`Unknown prompt: ${name}`);
1099
1263
  }
@@ -1311,6 +1475,418 @@ ${code}
1311
1475
  }]
1312
1476
  };
1313
1477
  }
1478
+ async function generateManageLayersPrompt(args) {
1479
+ const { action = "list", layers = "", color = "" } = args;
1480
+ const layerList = layers ? layers.split(/[,, ]+/) : [];
1481
+ const codeMap = {
1482
+ list: `(layer:list)`,
1483
+ make: `(layer:make "${layerList[0] || "NEW-LAYER"}" ${color || "7"} "Continuous" 0)`,
1484
+ freeze: `(mapcar (function (lambda (x) (layer:freeze x 1))) '${JSON.stringify(layerList.length ? layerList : ["0"])})`,
1485
+ lock: `(mapcar (function (lambda (x) (layer:lock x 1))) '${JSON.stringify(layerList.length ? layerList : ["0"])})`,
1486
+ off: `(mapcar (function (lambda (x) (layer:off x))) '${JSON.stringify(layerList.length ? layerList : ["0"])})`,
1487
+ delete: `(mapcar (function (lambda (x) (layer:delete x))) '${JSON.stringify(layerList.length ? layerList : ["0"]).replace(/"/g, '"')})`
1488
+ };
1489
+ const code = codeMap[action] || codeMap.list;
1490
+ const descMap = {
1491
+ list: "\u5217\u51FA\u6240\u6709\u56FE\u5C42",
1492
+ make: `\u521B\u5EFA\u56FE\u5C42 ${layerList[0] || "NEW-LAYER"}\uFF0C\u989C\u8272 ${color || "7"}`,
1493
+ freeze: `\u51BB\u7ED3\u56FE\u5C42: ${layerList.join(", ") || "\u672A\u6307\u5B9A"}`,
1494
+ lock: `\u9501\u5B9A\u56FE\u5C42: ${layerList.join(", ") || "\u672A\u6307\u5B9A"}`,
1495
+ off: `\u5173\u95ED\u56FE\u5C42: ${layerList.join(", ") || "\u672A\u6307\u5B9A"}`,
1496
+ delete: `\u5220\u9664\u56FE\u5C42: ${layerList.join(", ") || "\u672A\u6307\u5B9A"}`
1497
+ };
1498
+ return {
1499
+ messages: [{
1500
+ role: "user",
1501
+ content: {
1502
+ type: "text",
1503
+ text: `${descMap[action] || descMap.list}
1504
+
1505
+ \`\`\`lisp
1506
+ ${code}
1507
+ \`\`\`
1508
+
1509
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1510
+ }
1511
+ }]
1512
+ };
1513
+ }
1514
+ async function generateManageBlocksPrompt(args) {
1515
+ const { action = "list", blockName = "\u5757\u540D", insertPoint = "0,0", scale = "1" } = args;
1516
+ const pt = insertPoint.split(",").map(Number);
1517
+ const codeMap = {
1518
+ list: `(block:list)`,
1519
+ insert: `(block:insert "${blockName}" "${blockName}" (list ${pt[0] || 0} ${pt[1] || 0}) 0 ${scale})`,
1520
+ attributes: `(block:get-attributes (car (pickset:to-list (ssget "_X" (list (cons 2 "${blockName}"))))))`,
1521
+ dynprops: `(block:get-dynamic-properties (car (pickset:to-list (ssget "_X" (list (cons 2 "${blockName}"))))))`
1522
+ };
1523
+ const code = codeMap[action] || codeMap.list;
1524
+ const descMap = {
1525
+ list: "\u5217\u51FA\u5F53\u524D\u56FE\u7EB8\u4E2D\u6240\u6709\u5757\u5B9A\u4E49",
1526
+ insert: `\u63D2\u5165\u5757 "${blockName}" \u5230\u70B9 (${pt[0] || 0}, ${pt[1] || 0})\uFF0C\u6BD4\u4F8B ${scale}`,
1527
+ attributes: `\u83B7\u53D6\u5757 "${blockName}" \u7684\u5C5E\u6027\u6807\u7B7E-\u503C\u5217\u8868`,
1528
+ dynprops: `\u83B7\u53D6\u52A8\u6001\u5757 "${blockName}" \u7684\u53EF\u8C03\u5C5E\u6027`
1529
+ };
1530
+ return {
1531
+ messages: [{
1532
+ role: "user",
1533
+ content: {
1534
+ type: "text",
1535
+ text: `${descMap[action] || descMap.list}
1536
+
1537
+ \`\`\`lisp
1538
+ ${code}
1539
+ \`\`\`
1540
+
1541
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1542
+ }
1543
+ }]
1544
+ };
1545
+ }
1546
+ async function generateCurveAnalysisPrompt(args) {
1547
+ const { action = "inters", distance = "100" } = args;
1548
+ const codeMap = {
1549
+ inters: `(progn
1550
+ (setq ss (ssget "_X" (list (cons 0 "LWPOLYLINE,LINE,ARC,CIRCLE"))))
1551
+ (if (and ss (>= (sslength ss) 2))
1552
+ (progn
1553
+ (setq elst (pickset:to-list ss))
1554
+ (setq e1 (car elst) e2 (cadr elst))
1555
+ (curve:inters e1 e2 0)
1556
+ )
1557
+ )
1558
+ )`,
1559
+ subsegments: `(progn
1560
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "LWPOLYLINE"))))))
1561
+ (if e (curve:subsegments e))
1562
+ )`,
1563
+ closestpoint: `(progn
1564
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "LWPOLYLINE,LINE,ARC,CIRCLE"))))))
1565
+ (if e (curve:pickclosepointto e (getpoint "\\n\u9009\u62E9\u53C2\u8003\u70B9: ")))
1566
+ )`,
1567
+ join: `(progn
1568
+ (setq ss (ssget (list (cons 0 "LINE,LWPOLYLINE"))))
1569
+ (if ss (curve:join (pickset:to-list ss) ${distance}))
1570
+ )`
1571
+ };
1572
+ const code = codeMap[action] || codeMap.inters;
1573
+ const descMap = {
1574
+ inters: "\u9009\u62E9\u524D\u4E24\u4E2A\u66F2\u7EBF\u5BF9\u8C61\uFF0C\u8BA1\u7B97\u5176\u4EA4\u70B9\uFF08\u53EF\u6307\u5B9A LWPOLYLINE, LINE, ARC, CIRCLE\uFF09",
1575
+ subsegments: "\u9009\u62E9\u4E00\u4E2ALWPOLYLINE\uFF0C\u8FD4\u56DE\u5176\u5B50\u6BB5\u6570",
1576
+ closestpoint: "\u9009\u62E9\u4E00\u4E2A\u66F2\u7EBF\u5BF9\u8C61\uFF0C\u7136\u540E\u62FE\u53D6\u4E00\u4E2A\u70B9\uFF0C\u8FD4\u56DE\u66F2\u7EBF\u4E0A\u79BB\u8BE5\u70B9\u6700\u8FD1\u7684\u70B9",
1577
+ join: "\u9009\u62E9LINE/LWPOLYLINE\u7EBF\u6BB5\uFF0C\u7528 PEDIT Join \u5408\u5E76\uFF0C\u5BB9\u5DEE\u8DDD\u79BB=" + distance
1578
+ };
1579
+ return {
1580
+ messages: [{
1581
+ role: "user",
1582
+ content: {
1583
+ type: "text",
1584
+ text: `\u66F2\u7EBF\u64CD\u4F5C\uFF1A${descMap[action] || descMap.inters}
1585
+
1586
+ \`\`\`lisp
1587
+ ${code}
1588
+ \`\`\`
1589
+
1590
+ \u63D0\u793A\uFF1A\u786E\u4FDD CAD \u4E2D\u5DF2\u6709\u5BF9\u5E94\u56FE\u5F62\u5BF9\u8C61\u3002`
1591
+ }
1592
+ }]
1593
+ };
1594
+ }
1595
+ async function generateGeometryCalcPrompt(args) {
1596
+ const { action = "centroid", points = "0,0;100,0;100,100;0,100" } = args;
1597
+ const ptList = points.split(";").map((p) => {
1598
+ const [x, y] = p.split(",").map(Number);
1599
+ return `(list ${x} ${y})`;
1600
+ });
1601
+ const ptsStr = `(list ${ptList.join(" ")})`;
1602
+ const codeMap = {
1603
+ centroid: `(point:centroid ${ptsStr})`,
1604
+ "convexhull": `(geometry:convexhull-by-graham-scan ${ptsStr})`,
1605
+ "dist-point-line": `(progn
1606
+ (setq ss (ssget ":S" (list (cons 0 "LINE"))))
1607
+ (if ss
1608
+ (progn
1609
+ (setq e (car (pickset:to-list ss)))
1610
+ (setq p1 (cdr (assoc 10 (entget e))))
1611
+ (setq p2 (cdr (assoc 11 (entget e))))
1612
+ (geometry:dist-pt-line (getpoint "\\n\u9009\u62E9\u6D4B\u91CF\u70B9: ") (list p1 p2))
1613
+ )
1614
+ )
1615
+ )`,
1616
+ "in-curve-p": `(progn
1617
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "LWPOLYLINE"))))))
1618
+ (if e (point:in-curve-p (getpoint "\\n\u9009\u62E9\u6D4B\u8BD5\u70B9: ") e))
1619
+ )`,
1620
+ transform: `(matrix:transformation (list 0 0 0) (list 2 2 1) 0 (list 0 0 0))`
1621
+ };
1622
+ const code = codeMap[action] || codeMap.centroid;
1623
+ const descMap = {
1624
+ centroid: `\u8BA1\u7B97 ${points} \u7684\u51E0\u4F55\u4E2D\u5FC3\uFF08\u8D28\u5FC3\uFF09`,
1625
+ convexhull: `\u8BA1\u7B97 ${points} \u7684\u51F8\u5305\uFF08Graham Scan \u7B97\u6CD5\uFF09`,
1626
+ "dist-point-line": "\u9009\u62E9\u4E00\u6761\u76F4\u7EBF\uFF0C\u7136\u540E\u62FE\u53D6\u4E00\u4E2A\u70B9\uFF0C\u8BA1\u7B97\u70B9\u5230\u76F4\u7EBF\u7684\u8DDD\u79BB",
1627
+ "in-curve-p": "\u9009\u62E9\u4E00\u4E2A\u95ED\u5408 LWPOLYLINE\uFF0C\u7136\u540E\u62FE\u53D6\u4E00\u4E2A\u70B9\uFF0C\u68C0\u6D4B\u70B9\u662F\u5426\u5728\u66F2\u7EBF\u5185\u90E8",
1628
+ transform: "\u5750\u6807\u53D8\u6362\u793A\u4F8B\uFF1A\u7F29\u653E2\u500D (matrix:transformation \u5E73\u79FB \u7F29\u653E \u65CB\u8F6C \u57FA\u70B9)"
1629
+ };
1630
+ return {
1631
+ messages: [{
1632
+ role: "user",
1633
+ content: {
1634
+ type: "text",
1635
+ text: `\u51E0\u4F55\u8BA1\u7B97\uFF1A${descMap[action] || descMap.centroid}
1636
+
1637
+ \`\`\`lisp
1638
+ ${code}
1639
+ \`\`\`
1640
+
1641
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1642
+ }
1643
+ }]
1644
+ };
1645
+ }
1646
+ async function generateTextProcessPrompt(args) {
1647
+ const { action = "remove-fmt", markdown = "\u8FD9\u662F **\u7C97\u4F53** \u548C *\u659C\u4F53* \u6587\u672C" } = args;
1648
+ const codeMap = {
1649
+ "remove-fmt": `(progn
1650
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "MTEXT"))))))
1651
+ (if e (text:remove-fmt (cdr (assoc 1 (entget e)))))
1652
+ )`,
1653
+ "parse-mtext": `(progn
1654
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "MTEXT"))))))
1655
+ (if e (text:parse-mtext (cdr (assoc 1 (entget e)))))
1656
+ )`,
1657
+ "from-markdown": `(text:from-markdown "${markdown}")`,
1658
+ "mtext2text": `(progn
1659
+ (setq e (car (pickset:to-list (ssget ":S" (list (cons 0 "MTEXT"))))))
1660
+ (if e (text:mtext2text e))
1661
+ )`
1662
+ };
1663
+ const code = codeMap[action] || codeMap["remove-fmt"];
1664
+ const descMap = {
1665
+ "remove-fmt": "\u9009\u62E9\u4E00\u4E2AMTEXT\u5BF9\u8C61\uFF0C\u53BB\u9664\u6240\u6709\u683C\u5F0F\u4EE3\u7801\uFF0C\u8FD4\u56DE\u7EAF\u6587\u672C",
1666
+ "parse-mtext": "\u9009\u62E9\u4E00\u4E2AMTEXT\u5BF9\u8C61\uFF0C\u89E3\u6790\u4E3A (\u683C\u5F0F\u6216\u6587\u672C . \u5185\u5BB9) \u5217\u8868",
1667
+ "from-markdown": `\u5C06Markdown\u8F6C\u6362\u4E3AMTEXT\u683C\u5F0F\u4EE3\u7801\uFF1A
1668
+ ${markdown}`,
1669
+ "mtext2text": "\u9009\u62E9\u4E00\u4E2AMTEXT\u5BF9\u8C61\uFF0C\u5206\u89E3\u4E3A\u591A\u4E2A\u5355\u884CTEXT"
1670
+ };
1671
+ return {
1672
+ messages: [{
1673
+ role: "user",
1674
+ content: {
1675
+ type: "text",
1676
+ text: `\u6587\u672C\u5904\u7406\uFF1A${descMap[action] || descMap["remove-fmt"]}
1677
+
1678
+ \`\`\`lisp
1679
+ ${code}
1680
+ \`\`\`
1681
+
1682
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1683
+ }
1684
+ }]
1685
+ };
1686
+ }
1687
+ async function generatePicksetFilterPrompt(args) {
1688
+ const { action = "by-type", dxfType = "LINE", layerName = "0" } = args;
1689
+ const codeMap = {
1690
+ "by-type": `(progn
1691
+ (setq ss (ssget "_X" (list (cons 0 "${dxfType}"))))
1692
+ (if ss (list (sslength ss) (mapcar (function (lambda (x) (cdr (assoc 0 (entget x))))) (pickset:to-list ss))))
1693
+ )`,
1694
+ "by-layer": `(progn
1695
+ (setq ss (ssget "_X" (list (cons 8 "${layerName}"))))
1696
+ (if ss (list (sslength ss) (mapcar (function (lambda (x) (cdr (assoc 0 (entget x))))) (pickset:to-list ss))))
1697
+ )`,
1698
+ "by-box": `(progn
1699
+ (setq ss (ssget "_X"))
1700
+ (if ss (pickset:getbox ss 0))
1701
+ )`,
1702
+ erase: `(progn
1703
+ (setq ss (ssget (list (cons 0 "${dxfType}"))))
1704
+ (if ss (progn (pickset:erase ss) (princ (strcat "\u5DF2\u5220\u9664 " (itoa (sslength ss)) " \u4E2A " "${dxfType}" " \u5B9E\u4F53"))))
1705
+ )`,
1706
+ zoom: `(progn
1707
+ (setq ss (ssget "_X" (list (cons 0 "${dxfType}"))))
1708
+ (if ss (pickset:zoom ss))
1709
+ )`
1710
+ };
1711
+ const code = codeMap[action] || codeMap["by-type"];
1712
+ const descMap = {
1713
+ "by-type": `\u7EDF\u8BA1\u6240\u6709\u7C7B\u578B\u4E3A ${dxfType} \u7684\u5B9E\u4F53\u6570\u91CF`,
1714
+ "by-layer": `\u7EDF\u8BA1\u56FE\u5C42 ${layerName} \u4E0A\u7684\u5B9E\u4F53\u6570\u91CF\u548C\u7C7B\u578B`,
1715
+ "by-box": "\u8BA1\u7B97\u5168\u56FE\u9009\u62E9\u96C6\u7684\u8FB9\u754C\u6846",
1716
+ erase: `\u5220\u9664\u6240\u6709 ${dxfType} \u7C7B\u578B\u7684\u5B9E\u4F53`,
1717
+ zoom: `\u7F29\u653E\u5230\u6240\u6709 ${dxfType} \u7C7B\u578B\u7684\u5B9E\u4F53`
1718
+ };
1719
+ return {
1720
+ messages: [{
1721
+ role: "user",
1722
+ content: {
1723
+ type: "text",
1724
+ text: `\u9009\u62E9\u96C6\u64CD\u4F5C\uFF1A${descMap[action] || descMap["by-type"]}
1725
+
1726
+ \`\`\`lisp
1727
+ ${code}
1728
+ \`\`\`
1729
+
1730
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1731
+ }
1732
+ }]
1733
+ };
1734
+ }
1735
+ async function generateColorConvertPrompt(args) {
1736
+ const { action = "aci2rgb", value = "1" } = args;
1737
+ const codeMap = {
1738
+ aci2rgb: `(color:aci2rgb ${parseInt(value) || 1})`,
1739
+ rgb2css: `(color:rgb2css (list ${value.split(",").map((v) => parseInt(v) || 0).join(" ")}))`,
1740
+ truecolor2rgb: `(color:truecolor2rgb ${parseInt(value) || 16711680})`,
1741
+ rgb2truecolor: `(color:rgb2truecolor (list ${value.split(",").map((v) => parseInt(v) || 0).join(" ")}))`,
1742
+ rgb: `(color:rgb ${value.split(",").map((v) => parseInt(v) || 0).join(" ")})`
1743
+ };
1744
+ const code = codeMap[action] || codeMap.aci2rgb;
1745
+ const descMap = {
1746
+ aci2rgb: `ACI\u989C\u8272\u7D22\u5F15 ${value} \u8F6CRGB`,
1747
+ rgb2css: `RGB (${value || "255,0,0"}) \u8F6CCSS\u989C\u8272 #FFFFFF`,
1748
+ truecolor2rgb: `TrueColor\u6574\u6570 ${value} \u8F6CRGB\u5217\u8868`,
1749
+ rgb2truecolor: `RGB (${value || "255,0,0"}) \u8F6CTrueColor\u6574\u6570`,
1750
+ rgb: `\u8BA1\u7B97RGB\u5408\u6210\u503C\uFF1AR ${value.split(",")[0] || 255} G ${value.split(",")[1] || 0} B ${value.split(",")[2] || 0}`
1751
+ };
1752
+ return {
1753
+ messages: [{
1754
+ role: "user",
1755
+ content: {
1756
+ type: "text",
1757
+ text: `${descMap[action] || descMap.aci2rgb}
1758
+
1759
+ \`\`\`lisp
1760
+ ${code}
1761
+ \`\`\`
1762
+
1763
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1764
+ }
1765
+ }]
1766
+ };
1767
+ }
1768
+ async function generateJsonExchangePrompt(args) {
1769
+ const { action = "encode", data = '(("name" . "\u5BA2\u5385") ("area" . 45.5) ("layer" . "A-WALL"))' } = args;
1770
+ const codeMap = {
1771
+ encode: `(json:encode-from-alist '${data})`,
1772
+ decode: `(json:parse "${data.replace(/"/g, '\\"')}")`,
1773
+ "decode-json": `(json:decode-json-from-string "${data.replace(/"/g, '\\"')}")`
1774
+ };
1775
+ const code = codeMap[action] || codeMap.encode;
1776
+ const descMap = {
1777
+ encode: `\u5C06alist\u6570\u636E\u7F16\u7801\u4E3AJSON\u5B57\u7B26\u4E32`,
1778
+ decode: `\u4F7F\u7528\u7EAFLisp\u89E3\u6790\u5668\u89E3\u6790JSON\u5B57\u7B26\u4E32`,
1779
+ "decode-json": `\u4F7F\u7528\u670D\u52A1\u5668API\u89E3\u7801JSON\u5B57\u7B26\u4E32\uFF08\u652F\u6301GBK\u7F16\u7801\uFF09`
1780
+ };
1781
+ return {
1782
+ messages: [{
1783
+ role: "user",
1784
+ content: {
1785
+ type: "text",
1786
+ text: `JSON\u6570\u636E\u4EA4\u6362\uFF1A${descMap[action] || descMap.encode}
1787
+
1788
+ \`\`\`lisp
1789
+ ${code}
1790
+ \`\`\`
1791
+
1792
+ \u6570\u636E:
1793
+ ${data}
1794
+
1795
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1796
+ }
1797
+ }]
1798
+ };
1799
+ }
1800
+ async function generateExcelReportPrompt(args) {
1801
+ const { visible = "false", savePath = "" } = args;
1802
+ const code = `(progn
1803
+ ;; 1. \u7EDF\u8BA1\u56FE\u7EB8\u5B9E\u4F53
1804
+ (setq ss (ssget "_X"))
1805
+ (setq elst (if ss (pickset:to-list ss) nil))
1806
+ (setq type-count (if elst (stat:stat (mapcar (function (lambda (x) (cdr (assoc 0 (entget x))))) elst)) nil))
1807
+
1808
+ ;; 2. \u521B\u5EFAExcel
1809
+ (setq xl (excel:new ${visible === "true" ? "nil" : "t"}))
1810
+
1811
+ ;; 3. \u5199\u8868\u5934
1812
+ (excel:set-rangevalue xl 1 "\u5B9E\u4F53\u7C7B\u578B")
1813
+ (excel:set-rangevalue xl "B1" "\u6570\u91CF")
1814
+
1815
+ ;; 4. \u5199\u5165\u6570\u636E
1816
+ (setq row 2)
1817
+ (foreach item type-count
1818
+ (excel:set-rangevalue xl (list row 1) (car item))
1819
+ (excel:set-rangevalue xl (list row 2) (cdr item))
1820
+ (setq row (1+ row))
1821
+ )
1822
+
1823
+ ;; 5. \u83B7\u53D6\u56FE\u5C42\u5217\u8868
1824
+ (setq layers (layer:list))
1825
+ (excel:set-rangevalue xl (list 1 4) "\u56FE\u5C42\u5217\u8868")
1826
+ (setq row 2)
1827
+ (foreach lay layers
1828
+ (excel:set-rangevalue xl (list row 4) lay)
1829
+ (setq row (1+ row))
1830
+ )
1831
+
1832
+ ${savePath ? `(excel:saveas xl "${savePath}")` : ""}
1833
+ (princ (strcat "Excel\u62A5\u8868\u5DF2\u751F\u6210\uFF0C\u5171 " (itoa (1- row)) " \u884C\u6570\u636E"))
1834
+ )`;
1835
+ return {
1836
+ messages: [{
1837
+ role: "user",
1838
+ content: {
1839
+ type: "text",
1840
+ text: `\u5BFC\u51FACAD\u5B9E\u4F53\u7EDF\u8BA1\u5230Excel\u62A5\u8868\uFF1A
1841
+
1842
+ \`\`\`lisp
1843
+ ${code}
1844
+ \`\`\`
1845
+ ${savePath ? `
1846
+ \u4FDD\u5B58\u8DEF\u5F84: ${savePath}` : "\n\u6CE8\u610F\uFF1A\u8BF7\u66FF\u6362Excel\u4E3A\u53EF\u89C1\u6A21\u5F0F\u540E\u624B\u52A8\u4FDD\u5B58"}
1847
+
1848
+ \u4F7F\u7528 \`eval_lisp\` \u6267\u884C\u3002`
1849
+ }
1850
+ }]
1851
+ };
1852
+ }
1853
+ async function generateStringProcessPrompt(args) {
1854
+ const { action = "format", input = "Hello, {0}!", arg1 = "World", arg2 = "" } = args;
1855
+ const codeMap = {
1856
+ format: `(string:format "${input}" (list "${arg1}"))`,
1857
+ split: `(string:split "${input}" "${arg1}")`,
1858
+ "subst-all": `(string:subst-all "${arg2}" "${arg1}" "${input}")`,
1859
+ regexp: `(re:match "${arg1}" "${input}")`,
1860
+ trim: `(string:trim-space "${input}")`,
1861
+ number2chinese: `(string:number2chinese ${parseInt(input) || 12345})`,
1862
+ "to-list": `(string:to-list "${input}" "${arg1}")`
1863
+ };
1864
+ const code = codeMap[action] || codeMap.format;
1865
+ const descMap = {
1866
+ format: `\u683C\u5F0F\u5316: ${input} \u53C2\u6570: ${arg1}`,
1867
+ split: `\u62C6\u5206: "${input}" \u6309 "${arg1}" \u5206\u9694`,
1868
+ "subst-all": `\u66FF\u6362: \u5C06 "${input}" \u4E2D\u7684 "${arg1}" \u66FF\u6362\u4E3A "${arg2}"`,
1869
+ regexp: `\u6B63\u5219\u5339\u914D: "${input}" \u6A21\u5F0F: ${arg1}`,
1870
+ trim: `\u53BB\u9664\u9996\u5C3E\u7A7A\u683C: "${input}"`,
1871
+ number2chinese: `\u6570\u5B57 ${parseInt(input) || 12345} \u8F6C\u4E2D\u6587\u5927\u5199`,
1872
+ "to-list": `\u6309\u5206\u9694\u7B26 "${arg1}" \u62C6\u5206 "${input}" \u4E3A\u5217\u8868`
1873
+ };
1874
+ return {
1875
+ messages: [{
1876
+ role: "user",
1877
+ content: {
1878
+ type: "text",
1879
+ text: `${descMap[action] || descMap.format}
1880
+
1881
+ \`\`\`lisp
1882
+ ${code}
1883
+ \`\`\`
1884
+
1885
+ \u4F7F\u7528 \`eval_lisp_with_result\` \u6267\u884C\u83B7\u53D6\u7ED3\u679C\u3002`
1886
+ }
1887
+ }]
1888
+ };
1889
+ }
1314
1890
 
1315
1891
  // src/session-manager.js
1316
1892
  var Session = class {
@@ -2041,14 +2617,16 @@ async function handleToolCall(name, args) {
2041
2617
  }
2042
2618
  function notifyResourceChanges(toolName) {
2043
2619
  const resourceMap = {
2044
- connect_cad: ["atlisp://cad/info"],
2620
+ connect_cad: ["atlisp://cad/info", "atlisp://cad/layers", "atlisp://dwg/name", "atlisp://dwg/path", "atlisp://packages"],
2045
2621
  new_document: ["atlisp://dwg/name", "atlisp://dwg/path", "atlisp://cad/layers", "atlisp://cad/entities"],
2046
2622
  install_package: ["atlisp://packages"],
2047
- install_atlisp: ["atlisp://packages"]
2623
+ install_atlisp: ["atlisp://packages", "atlisp://cad/info"],
2624
+ init_atlisp: ["atlisp://packages", "atlisp://cad/info"]
2048
2625
  };
2049
2626
  const uris = resourceMap[toolName];
2050
2627
  if (uris) {
2051
2628
  for (const uri of uris) {
2629
+ clearCache(uri);
2052
2630
  if (isSubscribed(uri)) {
2053
2631
  notify(uri, null);
2054
2632
  }
@@ -129,7 +129,7 @@ const cadSendWithResult = edge.func(function() {/*
129
129
  string platform = d.platform.ToString();
130
130
  string encoding = d.encoding != null ? d.encoding.ToString() : "";
131
131
  string progId = platform + ".Application";
132
- string tempDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "@lisp");
132
+ string tempDir = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "@lisp", "tmp");
133
133
  System.IO.Directory.CreateDirectory(tempDir);
134
134
 
135
135
  tempFile = System.IO.Path.Combine(tempDir, "atlisp_result_" + System.Guid.NewGuid().ToString("N") + ".txt");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/mcp",
3
- "version": "1.3.5",
3
+ "version": "1.3.8",
4
4
  "description": "MCP Server for @lisp on CAD",
5
5
  "type": "module",
6
6
  "bin": {