@atlisp/mcp 1.8.23 → 1.8.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -4
- package/dist/atlisp-mcp.js +1443 -857
- package/dist/cad-rothelper.dll +0 -0
- package/dist/cad-worker.js +239 -176
- package/dist/config.js +59 -56
- package/dist/handlers/batch-doc-handlers.js +242 -0
- package/dist/handlers/cad-handlers.js +10 -3
- package/dist/handlers/meta-handlers.js +70 -0
- package/dist/handlers/resource-cache.js +48 -16
- package/dist/handlers/resource-defs.js +3 -0
- package/dist/handlers/resource-handlers.js +123 -0
- package/dist/handlers/skill-handlers.js +152 -0
- package/dist/lisp-security.js +65 -0
- package/dist/prompts/definitions/workflow-batch-doc.json +27 -0
- package/package.json +3 -2
package/dist/atlisp-mcp.js
CHANGED
|
@@ -7,10 +7,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
8
8
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
9
9
|
});
|
|
10
|
-
var __glob = (map) => (
|
|
11
|
-
var fn = map[
|
|
10
|
+
var __glob = (map) => (path21) => {
|
|
11
|
+
var fn = map[path21];
|
|
12
12
|
if (fn) return fn();
|
|
13
|
-
throw new Error("Module not found in bundle: " +
|
|
13
|
+
throw new Error("Module not found in bundle: " + path21);
|
|
14
14
|
};
|
|
15
15
|
var __esm = (fn, res) => function __init() {
|
|
16
16
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -37,7 +37,7 @@ function parseArgs() {
|
|
|
37
37
|
} else if (args[i] === "--ws") {
|
|
38
38
|
result.transport = "ws";
|
|
39
39
|
} else if (args[i] === "--port" && args[i + 1]) {
|
|
40
|
-
result.port = args[i + 1];
|
|
40
|
+
result.port = parseInt(args[i + 1], 10);
|
|
41
41
|
i++;
|
|
42
42
|
} else if (args[i] === "--host" && args[i + 1]) {
|
|
43
43
|
result.host = args[i + 1];
|
|
@@ -111,41 +111,42 @@ var envSchema, configSchema, cliArgs, envResult, env, configFilePath, fileConfig
|
|
|
111
111
|
var init_config = __esm({
|
|
112
112
|
"src/config.js"() {
|
|
113
113
|
envSchema = z.object({
|
|
114
|
-
PORT: z.
|
|
114
|
+
PORT: z.coerce.number().optional().default(8110),
|
|
115
115
|
HOST: z.string().optional().default("0.0.0.0"),
|
|
116
116
|
TRANSPORT: z.enum(["http", "stdio", "ws"]).optional().default("http"),
|
|
117
117
|
MCP_API_KEY: z.string().optional().default(""),
|
|
118
|
-
ENABLE_SSE: z.
|
|
119
|
-
MESSAGE_TIMEOUT: z.
|
|
120
|
-
HEARTBEAT_INTERVAL: z.
|
|
121
|
-
BUSY_RETRIES: z.
|
|
122
|
-
BUSY_DELAY: z.
|
|
123
|
-
ENABLE_CORS: z.
|
|
124
|
-
CORS_ORIGIN: z.string().optional().default("
|
|
125
|
-
RATE_LIMIT_WINDOW: z.
|
|
126
|
-
RATE_LIMIT_MAX: z.
|
|
127
|
-
RESOURCE_CACHE_TTL: z.
|
|
128
|
-
FUNCTION_LIB_CACHE_TTL: z.
|
|
129
|
-
DEBUG: z.
|
|
118
|
+
ENABLE_SSE: z.coerce.boolean().optional().default(true),
|
|
119
|
+
MESSAGE_TIMEOUT: z.coerce.number().optional().default(6e4),
|
|
120
|
+
HEARTBEAT_INTERVAL: z.coerce.number().optional().default(3e4),
|
|
121
|
+
BUSY_RETRIES: z.coerce.number().optional().default(10),
|
|
122
|
+
BUSY_DELAY: z.coerce.number().optional().default(500),
|
|
123
|
+
ENABLE_CORS: z.coerce.boolean().optional().default(true),
|
|
124
|
+
CORS_ORIGIN: z.string().optional().default("https://atlisp.cn"),
|
|
125
|
+
RATE_LIMIT_WINDOW: z.coerce.number().optional().default(6e4),
|
|
126
|
+
RATE_LIMIT_MAX: z.coerce.number().optional().default(100),
|
|
127
|
+
RESOURCE_CACHE_TTL: z.coerce.number().optional().default(5e3),
|
|
128
|
+
FUNCTION_LIB_CACHE_TTL: z.coerce.number().optional().default(3e5),
|
|
129
|
+
DEBUG: z.coerce.boolean().optional().default(false),
|
|
130
130
|
DEBUG_FILE: z.string().optional().default(""),
|
|
131
131
|
FUNCTION_LIB_URL: z.string().optional().default("http://s3.atlisp.cn/json/functions.json"),
|
|
132
132
|
CONFIG_FILE: z.string().optional().default(""),
|
|
133
|
-
API_KEY_RATE_LIMIT: z.
|
|
134
|
-
METRICS_ENABLED: z.
|
|
135
|
-
REQUEST_LOG_ENABLED: z.
|
|
133
|
+
API_KEY_RATE_LIMIT: z.coerce.number().optional().default(1e3),
|
|
134
|
+
METRICS_ENABLED: z.coerce.boolean().optional().default(true),
|
|
135
|
+
REQUEST_LOG_ENABLED: z.coerce.boolean().optional().default(true),
|
|
136
136
|
SSL_KEY_PATH: z.string().optional().default(""),
|
|
137
137
|
SSL_CERT_PATH: z.string().optional().default(""),
|
|
138
138
|
LLM_API_KEY: z.string().optional().default(""),
|
|
139
139
|
LLM_API_URL: z.string().optional().default("https://api.openai.com/v1/chat/completions"),
|
|
140
140
|
LLM_MODEL: z.string().optional().default("gpt-4o-mini"),
|
|
141
|
-
LLM_MAX_TOKENS: z.
|
|
142
|
-
LLM_TEMPERATURE: z.
|
|
143
|
-
WORKER_POOL_SIZE: z.
|
|
141
|
+
LLM_MAX_TOKENS: z.coerce.number().optional().default(4096),
|
|
142
|
+
LLM_TEMPERATURE: z.coerce.number().optional().default(0.7),
|
|
143
|
+
WORKER_POOL_SIZE: z.coerce.number().optional().default(2),
|
|
144
144
|
LINT_PRESET: z.string().optional().default(""),
|
|
145
145
|
LINT_CONFIG_PATH: z.string().optional().default(""),
|
|
146
146
|
LINT_LEVEL: z.string().optional().default(""),
|
|
147
|
-
NO_LINT: z.
|
|
148
|
-
SECURITY_LEVEL: z.string().optional().default("strict")
|
|
147
|
+
NO_LINT: z.coerce.boolean().optional().default(false),
|
|
148
|
+
SECURITY_LEVEL: z.string().optional().default("strict"),
|
|
149
|
+
CLIENT_ID: z.string().optional().default("")
|
|
149
150
|
});
|
|
150
151
|
configSchema = z.object({
|
|
151
152
|
port: z.number().optional(),
|
|
@@ -188,7 +189,8 @@ var init_config = __esm({
|
|
|
188
189
|
lintConfigPath: z.string().optional(),
|
|
189
190
|
lintLevel: z.string().optional(),
|
|
190
191
|
noLint: z.boolean().optional(),
|
|
191
|
-
securityLevel: z.enum(["strict", "standard", "relaxed"]).optional()
|
|
192
|
+
securityLevel: z.enum(["strict", "standard", "relaxed"]).optional(),
|
|
193
|
+
clientId: z.string().optional()
|
|
192
194
|
});
|
|
193
195
|
cliArgs = parseArgs();
|
|
194
196
|
envResult = envSchema.safeParse(process.env);
|
|
@@ -200,43 +202,44 @@ var init_config = __esm({
|
|
|
200
202
|
configFilePath = env.CONFIG_FILE || cliArgs.configFile || path.join(os.homedir(), ".atlisp", "atlisp.config.json");
|
|
201
203
|
fileConfig = loadConfigFile(configFilePath);
|
|
202
204
|
config = {
|
|
203
|
-
port: fileConfig?.port
|
|
204
|
-
host: fileConfig?.host
|
|
205
|
+
port: fileConfig?.port ?? cliArgs.port ?? env.PORT,
|
|
206
|
+
host: fileConfig?.host ?? cliArgs.host ?? env.HOST,
|
|
205
207
|
transport: fileConfig?.transport ?? cliArgs.transport ?? env.TRANSPORT,
|
|
206
|
-
apiKey: fileConfig?.apiKey
|
|
207
|
-
enableSse: fileConfig?.enableSse ?? env.ENABLE_SSE
|
|
208
|
-
messageTimeout: fileConfig?.messageTimeout
|
|
209
|
-
heartbeatInterval: fileConfig?.heartbeatInterval
|
|
210
|
-
busyRetries: fileConfig?.busyRetries
|
|
211
|
-
busyDelay: fileConfig?.busyDelay
|
|
212
|
-
enableCors: fileConfig?.enableCors ?? env.ENABLE_CORS
|
|
213
|
-
corsOrigin: fileConfig?.corsOrigin
|
|
214
|
-
rateLimitWindow: fileConfig?.rateLimitWindow
|
|
215
|
-
rateLimitMax: fileConfig?.rateLimitMax
|
|
216
|
-
resourceCacheTtl: fileConfig?.resourceCacheTtl
|
|
217
|
-
functionLibCacheTtl: fileConfig?.functionLibCacheTtl
|
|
218
|
-
debug: fileConfig?.debug ?? env.DEBUG
|
|
219
|
-
debugFile: fileConfig?.debugFile
|
|
220
|
-
functionLibUrl: fileConfig?.functionLibUrl
|
|
208
|
+
apiKey: fileConfig?.apiKey ?? env.MCP_API_KEY,
|
|
209
|
+
enableSse: fileConfig?.enableSse ?? env.ENABLE_SSE,
|
|
210
|
+
messageTimeout: fileConfig?.messageTimeout ?? env.MESSAGE_TIMEOUT,
|
|
211
|
+
heartbeatInterval: fileConfig?.heartbeatInterval ?? env.HEARTBEAT_INTERVAL,
|
|
212
|
+
busyRetries: fileConfig?.busyRetries ?? env.BUSY_RETRIES,
|
|
213
|
+
busyDelay: fileConfig?.busyDelay ?? env.BUSY_DELAY,
|
|
214
|
+
enableCors: fileConfig?.enableCors ?? env.ENABLE_CORS,
|
|
215
|
+
corsOrigin: fileConfig?.corsOrigin ?? env.CORS_ORIGIN,
|
|
216
|
+
rateLimitWindow: fileConfig?.rateLimitWindow ?? env.RATE_LIMIT_WINDOW,
|
|
217
|
+
rateLimitMax: fileConfig?.rateLimitMax ?? env.RATE_LIMIT_MAX,
|
|
218
|
+
resourceCacheTtl: fileConfig?.resourceCacheTtl ?? env.RESOURCE_CACHE_TTL,
|
|
219
|
+
functionLibCacheTtl: fileConfig?.functionLibCacheTtl ?? env.FUNCTION_LIB_CACHE_TTL,
|
|
220
|
+
debug: fileConfig?.debug ?? env.DEBUG,
|
|
221
|
+
debugFile: fileConfig?.debugFile ?? env.DEBUG_FILE,
|
|
222
|
+
functionLibUrl: fileConfig?.functionLibUrl ?? env.FUNCTION_LIB_URL,
|
|
221
223
|
configFile: configFilePath,
|
|
222
|
-
apiKeyRateLimit: fileConfig?.apiKeyRateLimit
|
|
223
|
-
apiKeys: fileConfig?.apiKeys
|
|
224
|
-
metricsEnabled: fileConfig?.metricsEnabled ?? env.METRICS_ENABLED
|
|
225
|
-
requestLogEnabled: fileConfig?.requestLogEnabled ?? env.REQUEST_LOG_ENABLED
|
|
226
|
-
sslKey: fileConfig?.sslKey
|
|
227
|
-
sslCert: fileConfig?.sslCert
|
|
228
|
-
llmApiKey: fileConfig?.llmApiKey
|
|
229
|
-
llmApiUrl: fileConfig?.llmApiUrl
|
|
230
|
-
llmModel: fileConfig?.llmModel
|
|
231
|
-
llmMaxTokens: fileConfig?.llmMaxTokens
|
|
232
|
-
llmTemperature: fileConfig?.llmTemperature
|
|
233
|
-
maxPoolSize: fileConfig?.maxPoolSize
|
|
234
|
-
workerPoolSize: fileConfig?.workerPoolSize
|
|
235
|
-
lintPreset: fileConfig?.lintPreset
|
|
236
|
-
lintConfigPath: fileConfig?.lintConfigPath
|
|
237
|
-
lintLevel: fileConfig?.lintLevel
|
|
238
|
-
noLint: fileConfig?.noLint ?? cliArgs.noLint ?? env.NO_LINT
|
|
239
|
-
securityLevel: fileConfig?.securityLevel ?? cliArgs.securityLevel ?? (env.SECURITY_LEVEL || "strict")
|
|
224
|
+
apiKeyRateLimit: fileConfig?.apiKeyRateLimit ?? env.API_KEY_RATE_LIMIT,
|
|
225
|
+
apiKeys: fileConfig?.apiKeys ?? [],
|
|
226
|
+
metricsEnabled: fileConfig?.metricsEnabled ?? env.METRICS_ENABLED,
|
|
227
|
+
requestLogEnabled: fileConfig?.requestLogEnabled ?? env.REQUEST_LOG_ENABLED,
|
|
228
|
+
sslKey: fileConfig?.sslKey ?? env.SSL_KEY_PATH ?? cliArgs.sslKey,
|
|
229
|
+
sslCert: fileConfig?.sslCert ?? env.SSL_CERT_PATH ?? cliArgs.sslCert,
|
|
230
|
+
llmApiKey: fileConfig?.llmApiKey ?? env.LLM_API_KEY,
|
|
231
|
+
llmApiUrl: fileConfig?.llmApiUrl ?? env.LLM_API_URL,
|
|
232
|
+
llmModel: fileConfig?.llmModel ?? env.LLM_MODEL,
|
|
233
|
+
llmMaxTokens: fileConfig?.llmMaxTokens ?? env.LLM_MAX_TOKENS,
|
|
234
|
+
llmTemperature: fileConfig?.llmTemperature ?? env.LLM_TEMPERATURE,
|
|
235
|
+
maxPoolSize: fileConfig?.maxPoolSize ?? 3,
|
|
236
|
+
workerPoolSize: fileConfig?.workerPoolSize ?? env.WORKER_POOL_SIZE,
|
|
237
|
+
lintPreset: fileConfig?.lintPreset ?? cliArgs.lintPreset ?? (env.LINT_PRESET || void 0),
|
|
238
|
+
lintConfigPath: fileConfig?.lintConfigPath ?? cliArgs.lintConfigPath ?? (env.LINT_CONFIG_PATH || void 0),
|
|
239
|
+
lintLevel: fileConfig?.lintLevel ?? cliArgs.lintLevel ?? (env.LINT_LEVEL || void 0),
|
|
240
|
+
noLint: fileConfig?.noLint ?? cliArgs.noLint ?? env.NO_LINT,
|
|
241
|
+
securityLevel: fileConfig?.securityLevel ?? cliArgs.securityLevel ?? (env.SECURITY_LEVEL || "strict"),
|
|
242
|
+
clientId: fileConfig?.clientId ?? (env.CLIENT_ID || "")
|
|
240
243
|
};
|
|
241
244
|
if (config.lintConfigPath) process.env.LINT_CONFIG_PATH = config.lintConfigPath;
|
|
242
245
|
if (config.lintPreset) process.env.LINT_PRESET = config.lintPreset;
|
|
@@ -453,15 +456,89 @@ var init_metrics = __esm({
|
|
|
453
456
|
}
|
|
454
457
|
});
|
|
455
458
|
|
|
459
|
+
// src/cad-circuit-breaker.js
|
|
460
|
+
var CB_CLOSED, CB_OPEN, CB_HALF_OPEN, CB_FAILURE_THRESHOLD, CB_RESET_TIMEOUT, CircuitBreaker;
|
|
461
|
+
var init_cad_circuit_breaker = __esm({
|
|
462
|
+
"src/cad-circuit-breaker.js"() {
|
|
463
|
+
CB_CLOSED = 0;
|
|
464
|
+
CB_OPEN = 1;
|
|
465
|
+
CB_HALF_OPEN = 2;
|
|
466
|
+
CB_FAILURE_THRESHOLD = 5;
|
|
467
|
+
CB_RESET_TIMEOUT = 1e4;
|
|
468
|
+
CircuitBreaker = class {
|
|
469
|
+
constructor(connectionId, onOpen, onHalfOpen) {
|
|
470
|
+
this._connId = connectionId;
|
|
471
|
+
this._state = CB_CLOSED;
|
|
472
|
+
this._failureCount = 0;
|
|
473
|
+
this._lastFailureTime = 0;
|
|
474
|
+
this._timer = null;
|
|
475
|
+
this._onOpen = onOpen;
|
|
476
|
+
this._onHalfOpen = onHalfOpen;
|
|
477
|
+
}
|
|
478
|
+
get state() {
|
|
479
|
+
return this._state;
|
|
480
|
+
}
|
|
481
|
+
get failureCount() {
|
|
482
|
+
return this._failureCount;
|
|
483
|
+
}
|
|
484
|
+
allowRequest() {
|
|
485
|
+
if (this._state === CB_OPEN) {
|
|
486
|
+
const elapsed = Date.now() - this._lastFailureTime;
|
|
487
|
+
if (elapsed >= CB_RESET_TIMEOUT) {
|
|
488
|
+
this._state = CB_HALF_OPEN;
|
|
489
|
+
if (this._onHalfOpen) this._onHalfOpen(this._connId);
|
|
490
|
+
} else {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
recordSuccess() {
|
|
497
|
+
this._state = CB_CLOSED;
|
|
498
|
+
this._failureCount = 0;
|
|
499
|
+
if (this._timer) {
|
|
500
|
+
clearTimeout(this._timer);
|
|
501
|
+
this._timer = null;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
recordFailure() {
|
|
505
|
+
this._failureCount++;
|
|
506
|
+
this._lastFailureTime = Date.now();
|
|
507
|
+
if (this._failureCount >= CB_FAILURE_THRESHOLD && this._state !== CB_OPEN) {
|
|
508
|
+
this._state = CB_OPEN;
|
|
509
|
+
if (this._onOpen) this._onOpen(this._connId);
|
|
510
|
+
this._timer = setTimeout(() => {
|
|
511
|
+
this._state = CB_HALF_OPEN;
|
|
512
|
+
if (this._onHalfOpen) this._onHalfOpen(this._connId);
|
|
513
|
+
}, CB_RESET_TIMEOUT);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
reset() {
|
|
517
|
+
this._state = CB_CLOSED;
|
|
518
|
+
this._failureCount = 0;
|
|
519
|
+
this._lastFailureTime = 0;
|
|
520
|
+
if (this._timer) {
|
|
521
|
+
clearTimeout(this._timer);
|
|
522
|
+
this._timer = null;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
|
|
456
529
|
// src/cad.js
|
|
457
530
|
var cad_exports = {};
|
|
458
531
|
__export(cad_exports, {
|
|
532
|
+
CommandQueue: () => CommandQueue,
|
|
533
|
+
ReadBatcher: () => ReadBatcher,
|
|
459
534
|
_setInstanceResolver: () => _setInstanceResolver,
|
|
460
535
|
cad: () => cad,
|
|
461
536
|
createCadConnection: () => createCadConnection,
|
|
462
537
|
default: () => cad_default,
|
|
463
538
|
getActiveConnection: () => getActiveConnection,
|
|
539
|
+
isReadCommand: () => isReadCommand,
|
|
464
540
|
onDocumentChanged: () => onDocumentChanged,
|
|
541
|
+
resolveCadConnection: () => resolveCadConnection,
|
|
465
542
|
setActiveConnection: () => setActiveConnection
|
|
466
543
|
});
|
|
467
544
|
import { spawn } from "child_process";
|
|
@@ -506,22 +583,21 @@ function _resolveConn() {
|
|
|
506
583
|
}
|
|
507
584
|
return _activeConnection;
|
|
508
585
|
}
|
|
509
|
-
|
|
586
|
+
function resolveCadConnection() {
|
|
587
|
+
return _resolveConn();
|
|
588
|
+
}
|
|
589
|
+
var __dirname, workerPath, MESSAGE_TIMEOUT, HEARTBEAT_INTERVAL, MAX_RESTART_ATTEMPTS, RESTART_BACKOFF_BASE, MAX_BUFFER_SIZE, PRIORITY_HIGH, PRIORITY_NORMAL, MAX_QUEUE_SIZE, READ_PREFIXES, _docChangeCallbacks, ReadBatcher, CommandQueue, CadConnection, _activeConnection, _resolveInstanceConn, cad, cad_default;
|
|
510
590
|
var init_cad = __esm({
|
|
511
591
|
"src/cad.js"() {
|
|
512
592
|
init_config();
|
|
513
593
|
init_metrics();
|
|
594
|
+
init_cad_circuit_breaker();
|
|
514
595
|
__dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
515
596
|
workerPath = path2.join(__dirname, "cad-worker.js");
|
|
516
597
|
MESSAGE_TIMEOUT = config_default.messageTimeout;
|
|
517
598
|
HEARTBEAT_INTERVAL = config_default.heartbeatInterval;
|
|
518
599
|
MAX_RESTART_ATTEMPTS = 5;
|
|
519
600
|
RESTART_BACKOFF_BASE = 1e3;
|
|
520
|
-
CB_CLOSED = 0;
|
|
521
|
-
CB_OPEN = 1;
|
|
522
|
-
CB_HALF_OPEN = 2;
|
|
523
|
-
CB_FAILURE_THRESHOLD = 5;
|
|
524
|
-
CB_RESET_TIMEOUT = 1e4;
|
|
525
601
|
MAX_BUFFER_SIZE = 1024 * 1024;
|
|
526
602
|
PRIORITY_HIGH = 0;
|
|
527
603
|
PRIORITY_NORMAL = 1;
|
|
@@ -708,10 +784,6 @@ var init_cad = __esm({
|
|
|
708
784
|
_heartbeatTimer = null;
|
|
709
785
|
_pendingRequests = /* @__PURE__ */ new Map();
|
|
710
786
|
_commandQueue = null;
|
|
711
|
-
_cbState = CB_CLOSED;
|
|
712
|
-
_cbFailureCount = 0;
|
|
713
|
-
_cbLastFailureTime = 0;
|
|
714
|
-
_cbTimer = null;
|
|
715
787
|
_restartCount = 0;
|
|
716
788
|
_restartTimer = null;
|
|
717
789
|
_activeDocName = null;
|
|
@@ -721,6 +793,11 @@ var init_cad = __esm({
|
|
|
721
793
|
constructor() {
|
|
722
794
|
this._connectionId = randomUUID().slice(0, 8);
|
|
723
795
|
this._commandQueue = new CommandQueue(this);
|
|
796
|
+
this._cb = new CircuitBreaker(
|
|
797
|
+
this._connectionId,
|
|
798
|
+
(id) => console.error(`[${id}] Circuit breaker OPEN`),
|
|
799
|
+
(id) => console.error(`[${id}] Circuit breaker HALF_OPEN, allowing trial request`)
|
|
800
|
+
);
|
|
724
801
|
}
|
|
725
802
|
get _workerPoolSize() {
|
|
726
803
|
return config_default.workerPoolSize || 2;
|
|
@@ -728,11 +805,15 @@ var init_cad = __esm({
|
|
|
728
805
|
isAvailable() {
|
|
729
806
|
return process.platform === "win32";
|
|
730
807
|
}
|
|
731
|
-
async connect(platform = null) {
|
|
808
|
+
async connect(platform = null, options = {}) {
|
|
732
809
|
if (!this.isAvailable()) return false;
|
|
733
|
-
this.
|
|
810
|
+
this._cb.recordSuccess();
|
|
734
811
|
try {
|
|
735
812
|
const msg = platform ? { type: "connect", platform } : { type: "connect" };
|
|
813
|
+
if (options.moniker) {
|
|
814
|
+
msg.moniker = options.moniker;
|
|
815
|
+
msg.monikerKey = options.key || "moniker";
|
|
816
|
+
}
|
|
736
817
|
const result = await this._sendMessage(msg);
|
|
737
818
|
if (result && result.success) {
|
|
738
819
|
this._version = result.version;
|
|
@@ -770,7 +851,7 @@ var init_cad = __esm({
|
|
|
770
851
|
throw new Error(result.error || "\u53D1\u9001\u5931\u8D25");
|
|
771
852
|
});
|
|
772
853
|
}
|
|
773
|
-
async sendCommandWithResult(code, encoding = null) {
|
|
854
|
+
async sendCommandWithResult(code, encoding = null, raw = false) {
|
|
774
855
|
if (!this.connected) throw new Error("\u672A\u8FDE\u63A5 CAD");
|
|
775
856
|
return new Promise((resolve, reject) => {
|
|
776
857
|
this._commandQueue.enqueue({
|
|
@@ -782,7 +863,12 @@ var init_cad = __esm({
|
|
|
782
863
|
reject
|
|
783
864
|
}, PRIORITY_NORMAL);
|
|
784
865
|
}).then((result) => {
|
|
785
|
-
if (result.success)
|
|
866
|
+
if (result.success) {
|
|
867
|
+
if (raw && result.rawBase64 !== void 0) {
|
|
868
|
+
return { text: result.result || "", rawBase64: result.rawBase64 };
|
|
869
|
+
}
|
|
870
|
+
return result.result || "";
|
|
871
|
+
}
|
|
786
872
|
throw new Error(result.error || "\u53D1\u9001\u5931\u8D25");
|
|
787
873
|
});
|
|
788
874
|
}
|
|
@@ -845,21 +931,8 @@ var init_cad = __esm({
|
|
|
845
931
|
return `Platform: ${this._product}, Version: ${this._version}, Status: Connected`;
|
|
846
932
|
}
|
|
847
933
|
async disconnect() {
|
|
848
|
-
this.
|
|
849
|
-
|
|
850
|
-
this._version = null;
|
|
851
|
-
this._product = null;
|
|
852
|
-
this._platform = null;
|
|
853
|
-
this._activeDocName = null;
|
|
854
|
-
this._monitorStarted = false;
|
|
855
|
-
this._commandQueue.clear();
|
|
856
|
-
this._cbState = CB_CLOSED;
|
|
857
|
-
this._cbFailureCount = 0;
|
|
858
|
-
if (this._cbTimer) {
|
|
859
|
-
clearTimeout(this._cbTimer);
|
|
860
|
-
this._cbTimer = null;
|
|
861
|
-
}
|
|
862
|
-
this._resetWorker();
|
|
934
|
+
this._reset();
|
|
935
|
+
this._cb.reset();
|
|
863
936
|
}
|
|
864
937
|
async ping() {
|
|
865
938
|
try {
|
|
@@ -878,12 +951,6 @@ var init_cad = __esm({
|
|
|
878
951
|
this._activeDocName = null;
|
|
879
952
|
this._monitorStarted = false;
|
|
880
953
|
this._commandQueue.clear();
|
|
881
|
-
this._cbState = CB_CLOSED;
|
|
882
|
-
this._cbFailureCount = 0;
|
|
883
|
-
if (this._cbTimer) {
|
|
884
|
-
clearTimeout(this._cbTimer);
|
|
885
|
-
this._cbTimer = null;
|
|
886
|
-
}
|
|
887
954
|
this._resetWorker();
|
|
888
955
|
}
|
|
889
956
|
_getQueueSize() {
|
|
@@ -892,44 +959,6 @@ var init_cad = __esm({
|
|
|
892
959
|
_getRestartCount() {
|
|
893
960
|
return this._restartCount;
|
|
894
961
|
}
|
|
895
|
-
// --- Circuit breaker ---
|
|
896
|
-
_cbSuccess() {
|
|
897
|
-
this._cbState = CB_CLOSED;
|
|
898
|
-
this._cbFailureCount = 0;
|
|
899
|
-
if (this._cbTimer) {
|
|
900
|
-
clearTimeout(this._cbTimer);
|
|
901
|
-
this._cbTimer = null;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
_cbFailure() {
|
|
905
|
-
this._cbFailureCount++;
|
|
906
|
-
this._cbLastFailureTime = Date.now();
|
|
907
|
-
if (this._cbFailureCount >= CB_FAILURE_THRESHOLD && this._cbState !== CB_OPEN) {
|
|
908
|
-
this._cbState = CB_OPEN;
|
|
909
|
-
console.error(`[${this._connectionId}] Circuit breaker OPEN after ${this._cbFailureCount} failures`);
|
|
910
|
-
this._cbTimer = setTimeout(() => {
|
|
911
|
-
this._cbState = CB_HALF_OPEN;
|
|
912
|
-
console.error(`[${this._connectionId}] Circuit breaker HALF_OPEN, allowing trial request`);
|
|
913
|
-
}, CB_RESET_TIMEOUT);
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
_cbAllowRequest() {
|
|
917
|
-
if (this._cbState === CB_OPEN) {
|
|
918
|
-
const elapsed = Date.now() - this._cbLastFailureTime;
|
|
919
|
-
if (elapsed >= CB_RESET_TIMEOUT) {
|
|
920
|
-
this._cbState = CB_HALF_OPEN;
|
|
921
|
-
console.error(`[${this._connectionId}] Circuit breaker auto-transition to HALF_OPEN`);
|
|
922
|
-
} else {
|
|
923
|
-
return false;
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
return true;
|
|
927
|
-
}
|
|
928
|
-
// --- Worker management ---
|
|
929
|
-
_isReadOnlyMessage(msg) {
|
|
930
|
-
if (msg.code) return isReadCommand(msg.code);
|
|
931
|
-
return false;
|
|
932
|
-
}
|
|
933
962
|
_spawnWorker(type) {
|
|
934
963
|
const w = spawn("node", [workerPath], { stdio: ["pipe", "pipe", "pipe"] });
|
|
935
964
|
w.connected = true;
|
|
@@ -940,7 +969,7 @@ var init_cad = __esm({
|
|
|
940
969
|
w.connected = false;
|
|
941
970
|
if (type === "primary") {
|
|
942
971
|
if (w !== this._primaryWorker) return;
|
|
943
|
-
this.
|
|
972
|
+
this._cb.recordFailure();
|
|
944
973
|
const exitError = new Error(`Primary worker exited with code ${code}`);
|
|
945
974
|
for (const [id, entry] of this._pendingRequests) {
|
|
946
975
|
clearTimeout(entry.timeout);
|
|
@@ -977,7 +1006,7 @@ var init_cad = __esm({
|
|
|
977
1006
|
this._primaryWorker = null;
|
|
978
1007
|
}
|
|
979
1008
|
this._primaryWorker = this._spawnWorker("primary");
|
|
980
|
-
this.
|
|
1009
|
+
this._cb.recordSuccess();
|
|
981
1010
|
if (!this._heartbeatTimer) this._startHeartbeat();
|
|
982
1011
|
this._restartCount = 0;
|
|
983
1012
|
}
|
|
@@ -1118,14 +1147,9 @@ var init_cad = __esm({
|
|
|
1118
1147
|
}, delay);
|
|
1119
1148
|
}
|
|
1120
1149
|
async _sendMessage(msg) {
|
|
1121
|
-
if (!this.
|
|
1150
|
+
if (!this._cb.allowRequest()) {
|
|
1122
1151
|
console.error(`[${this._connectionId}] Circuit breaker OPEN, auto-recovering...`);
|
|
1123
|
-
this.
|
|
1124
|
-
this._cbFailureCount = 0;
|
|
1125
|
-
if (this._cbTimer) {
|
|
1126
|
-
clearTimeout(this._cbTimer);
|
|
1127
|
-
this._cbTimer = null;
|
|
1128
|
-
}
|
|
1152
|
+
this._cb.reset();
|
|
1129
1153
|
await this._resetWorker();
|
|
1130
1154
|
await this._getWorker(false);
|
|
1131
1155
|
}
|
|
@@ -1141,17 +1165,17 @@ var init_cad = __esm({
|
|
|
1141
1165
|
const p = self._pendingRequests.get(requestId);
|
|
1142
1166
|
if (p) {
|
|
1143
1167
|
self._pendingRequests.delete(requestId);
|
|
1144
|
-
if (!noCircuitBreaker) self.
|
|
1168
|
+
if (!noCircuitBreaker) self._cb.recordFailure();
|
|
1145
1169
|
reject(new Error("Timeout waiting for worker"));
|
|
1146
1170
|
}
|
|
1147
1171
|
}, MESSAGE_TIMEOUT);
|
|
1148
1172
|
const entry = {
|
|
1149
1173
|
resolve: (v) => {
|
|
1150
|
-
if (!noCircuitBreaker && !entry._skipCb) self.
|
|
1174
|
+
if (!noCircuitBreaker && !entry._skipCb) self._cb.recordSuccess();
|
|
1151
1175
|
resolve(v);
|
|
1152
1176
|
},
|
|
1153
1177
|
reject: (e) => {
|
|
1154
|
-
if (!noCircuitBreaker && !entry._skipCb) self.
|
|
1178
|
+
if (!noCircuitBreaker && !entry._skipCb) self._cb.recordFailure();
|
|
1155
1179
|
reject(e);
|
|
1156
1180
|
},
|
|
1157
1181
|
timeout
|
|
@@ -1162,11 +1186,15 @@ var init_cad = __esm({
|
|
|
1162
1186
|
} catch (e) {
|
|
1163
1187
|
clearTimeout(timeout);
|
|
1164
1188
|
self._pendingRequests.delete(requestId);
|
|
1165
|
-
if (!noCircuitBreaker) self.
|
|
1189
|
+
if (!noCircuitBreaker) self._cb.recordFailure();
|
|
1166
1190
|
reject(new Error(`Failed to write to worker: ${e.message}`));
|
|
1167
1191
|
}
|
|
1168
1192
|
});
|
|
1169
1193
|
}
|
|
1194
|
+
_isReadOnlyMessage(msg) {
|
|
1195
|
+
if (msg.code) return isReadCommand(msg.code);
|
|
1196
|
+
return false;
|
|
1197
|
+
}
|
|
1170
1198
|
};
|
|
1171
1199
|
_activeConnection = new CadConnection();
|
|
1172
1200
|
_resolveInstanceConn = null;
|
|
@@ -1175,79 +1203,79 @@ var init_cad = __esm({
|
|
|
1175
1203
|
return _resolveConn().connected;
|
|
1176
1204
|
},
|
|
1177
1205
|
set connected(v) {
|
|
1178
|
-
|
|
1206
|
+
_resolveConn().connected = v;
|
|
1179
1207
|
},
|
|
1180
1208
|
get version() {
|
|
1181
|
-
return
|
|
1209
|
+
return _resolveConn()._version;
|
|
1182
1210
|
},
|
|
1183
1211
|
set version(v) {
|
|
1184
|
-
|
|
1212
|
+
_resolveConn()._version = v;
|
|
1185
1213
|
},
|
|
1186
1214
|
get product() {
|
|
1187
|
-
return
|
|
1215
|
+
return _resolveConn()._product;
|
|
1188
1216
|
},
|
|
1189
1217
|
set product(v) {
|
|
1190
|
-
|
|
1218
|
+
_resolveConn()._product = v;
|
|
1191
1219
|
},
|
|
1192
1220
|
get _platform() {
|
|
1193
|
-
return
|
|
1221
|
+
return _resolveConn()._platform;
|
|
1194
1222
|
},
|
|
1195
1223
|
set _platform(v) {
|
|
1196
|
-
|
|
1224
|
+
_resolveConn()._platform = v;
|
|
1197
1225
|
},
|
|
1198
1226
|
async connect(platform) {
|
|
1199
|
-
return
|
|
1227
|
+
return _resolveConn().connect(platform);
|
|
1200
1228
|
},
|
|
1201
1229
|
async sendCommand(code) {
|
|
1202
1230
|
return _resolveConn().sendCommand(code);
|
|
1203
1231
|
},
|
|
1204
|
-
async sendCommandWithResult(code, encoding) {
|
|
1205
|
-
return _resolveConn().sendCommandWithResult(code, encoding);
|
|
1232
|
+
async sendCommandWithResult(code, encoding, raw) {
|
|
1233
|
+
return _resolveConn().sendCommandWithResult(code, encoding, raw);
|
|
1206
1234
|
},
|
|
1207
1235
|
getVersion() {
|
|
1208
|
-
return
|
|
1236
|
+
return _resolveConn().getVersion();
|
|
1209
1237
|
},
|
|
1210
1238
|
getPlatform() {
|
|
1211
|
-
return
|
|
1239
|
+
return _resolveConn().getPlatform();
|
|
1212
1240
|
},
|
|
1213
1241
|
getConnectionId() {
|
|
1214
|
-
return
|
|
1242
|
+
return _resolveConn().getConnectionId();
|
|
1215
1243
|
},
|
|
1216
1244
|
isAvailable() {
|
|
1217
|
-
return
|
|
1245
|
+
return _resolveConn().isAvailable();
|
|
1218
1246
|
},
|
|
1219
1247
|
async isBusy() {
|
|
1220
|
-
return
|
|
1248
|
+
return _resolveConn().isBusy();
|
|
1221
1249
|
},
|
|
1222
1250
|
async hasDoc() {
|
|
1223
|
-
return
|
|
1251
|
+
return _resolveConn().hasDoc();
|
|
1224
1252
|
},
|
|
1225
1253
|
async newDoc() {
|
|
1226
|
-
return
|
|
1254
|
+
return _resolveConn().newDoc();
|
|
1227
1255
|
},
|
|
1228
1256
|
async bringToFront() {
|
|
1229
|
-
return
|
|
1257
|
+
return _resolveConn().bringToFront();
|
|
1230
1258
|
},
|
|
1231
1259
|
async getActiveDocInfo() {
|
|
1232
|
-
return
|
|
1260
|
+
return _resolveConn().getActiveDocInfo();
|
|
1233
1261
|
},
|
|
1234
1262
|
async getInfo() {
|
|
1235
|
-
return
|
|
1263
|
+
return _resolveConn().getInfo();
|
|
1236
1264
|
},
|
|
1237
1265
|
async disconnect() {
|
|
1238
|
-
return
|
|
1266
|
+
return _resolveConn().disconnect();
|
|
1239
1267
|
},
|
|
1240
1268
|
async ping() {
|
|
1241
|
-
return
|
|
1269
|
+
return _resolveConn().ping();
|
|
1242
1270
|
},
|
|
1243
1271
|
_reset() {
|
|
1244
|
-
return
|
|
1272
|
+
return _resolveConn()._reset();
|
|
1245
1273
|
},
|
|
1246
1274
|
_getQueueSize() {
|
|
1247
|
-
return
|
|
1275
|
+
return _resolveConn()._getQueueSize();
|
|
1248
1276
|
},
|
|
1249
1277
|
_getRestartCount() {
|
|
1250
|
-
return
|
|
1278
|
+
return _resolveConn()._getRestartCount();
|
|
1251
1279
|
}
|
|
1252
1280
|
};
|
|
1253
1281
|
cad_default = CadConnection;
|
|
@@ -1258,7 +1286,7 @@ var init_cad = __esm({
|
|
|
1258
1286
|
import path3 from "path";
|
|
1259
1287
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1260
1288
|
import { createRequire } from "module";
|
|
1261
|
-
var CAD_PLATFORMS, FILE_EXTENSIONS, __dirname2, require2, version, SERVER_NAME, SERVER_VERSION, SERVER_CAPABILITIES, MOCK_PACKAGES;
|
|
1289
|
+
var CAD_PLATFORMS, FILE_EXTENSIONS, __dirname2, require2, version, SERVER_NAME, SERVER_VERSION, SERVER_CAPABILITIES, MOCK_PACKAGES, CAD_RESOURCE_URIS;
|
|
1262
1290
|
var init_constants = __esm({
|
|
1263
1291
|
"src/constants.js"() {
|
|
1264
1292
|
CAD_PLATFORMS = ["AutoCAD", "ZWCAD", "GStarCAD", "BricsCAD"];
|
|
@@ -1281,6 +1309,17 @@ var init_constants = __esm({
|
|
|
1281
1309
|
completions: {}
|
|
1282
1310
|
};
|
|
1283
1311
|
MOCK_PACKAGES = [];
|
|
1312
|
+
CAD_RESOURCE_URIS = [
|
|
1313
|
+
"atlisp://cad/info",
|
|
1314
|
+
"atlisp://dwg/name",
|
|
1315
|
+
"atlisp://dwg/path",
|
|
1316
|
+
"atlisp://dwg/entities",
|
|
1317
|
+
"atlisp://dwg/tbl",
|
|
1318
|
+
"atlisp://dwg/block-refs",
|
|
1319
|
+
"atlisp://dwg/text-content",
|
|
1320
|
+
"atlisp://cad/dwgs",
|
|
1321
|
+
"atlisp://packages"
|
|
1322
|
+
];
|
|
1284
1323
|
}
|
|
1285
1324
|
});
|
|
1286
1325
|
|
|
@@ -1481,7 +1520,10 @@ var init_resource_defs = __esm({
|
|
|
1481
1520
|
{ uri: "atlisp://standards/drafting", name: "Drafting Standards", description: "CAD \u5236\u56FE\u89C4\u8303", mimeType: "application/json", subscribable: false },
|
|
1482
1521
|
{ uri: "atlisp://standards/coding", name: "Coding Standards", description: "@lisp \u7F16\u7801\u89C4\u8303", mimeType: "application/json", subscribable: false },
|
|
1483
1522
|
{ uri: "atlisp://dwg/context", name: "DWG Context", description: "\u5F53\u524D\u56FE\u7EB8\u4E0A\u4E0B\u6587\u6458\u8981\u3002\u8FD4\u56DE\u6587\u6863\u540D/\u8DEF\u5F84/\u5E03\u5C40/UCS/\u56FE\u5C42\u5217\u8868/\u5B9E\u4F53\u7EDF\u8BA1/\u7CFB\u7EDF\u53D8\u91CF\u7EC4\u5408\u4FE1\u606F\uFF0C\u5E2E\u52A9\u5FEB\u901F\u4E86\u89E3\u5F53\u524D CAD \u72B6\u6001", mimeType: "application/json", subscribable: true },
|
|
1484
|
-
{ uri: "atlisp://tools/relationships", name: "Tool Relationships", description: "\u5DE5\u5177\u4F9D\u8D56\u5173\u7CFB\u56FE\u3002\u63CF\u8FF0\u5DE5\u5177\u95F4\u7684\u8C03\u7528\u94FE\u5173\u7CFB\uFF08\u5982 select_entities \u2192 batch_delete\uFF09\uFF0C\u5E2E\u52A9\u7406\u89E3\u5DE5\u5177\u7EC4\u5408\u4F7F\u7528\u65B9\u5F0F", mimeType: "application/json", subscribable: false }
|
|
1523
|
+
{ uri: "atlisp://tools/relationships", name: "Tool Relationships", description: "\u5DE5\u5177\u4F9D\u8D56\u5173\u7CFB\u56FE\u3002\u63CF\u8FF0\u5DE5\u5177\u95F4\u7684\u8C03\u7528\u94FE\u5173\u7CFB\uFF08\u5982 select_entities \u2192 batch_delete\uFF09\uFF0C\u5E2E\u52A9\u7406\u89E3\u5DE5\u5177\u7EC4\u5408\u4F7F\u7528\u65B9\u5F0F", mimeType: "application/json", subscribable: false },
|
|
1524
|
+
{ uri: "atlisp://dwg/analysis", name: "Drawing Analysis", description: "\u5F53\u524D\u56FE\u7EB8\u7EFC\u5408\u5206\u6790\uFF1A\u5B9E\u4F53\u7C7B\u578B\u7EDF\u8BA1\u3001\u5757\u4F7F\u7528\u7EDF\u8BA1\u3001\u56FE\u5C42\u6458\u8981\u3001\u6587\u5B57\u7EDF\u8BA1\u3001\u7CFB\u7EDF\u53D8\u91CF\u5FEB\u7167\u3002\u652F\u6301 ?type=summary\uFF08\u9ED8\u8BA4\uFF09\u6216 ?type=detailed", mimeType: "application/json", subscribable: true },
|
|
1525
|
+
{ uri: "atlisp://tools/categories", name: "Tool Categories", description: "\u5DE5\u5177\u5206\u7C7B\u6982\u89C8\u3002\u5217\u51FA\u6240\u6709\u5206\u7C7B\u53CA\u5176\u5305\u542B\u7684\u5DE5\u5177\u6570\u91CF", mimeType: "application/json", subscribable: false },
|
|
1526
|
+
{ uri: "atlisp://dwg/standards/check", name: "Drawing Standards Check", description: "\u68C0\u67E5\u5F53\u524D\u56FE\u7EB8\u662F\u5426\u7B26\u5408\u52A0\u8F7D\u7684\u5236\u56FE\u89C4\u8303\uFF08\u56FE\u5C42\u547D\u540D\u3001\u989C\u8272\u3001\u7EBF\u578B\u7B49\u89C4\u5219\uFF09", mimeType: "application/json", subscribable: false }
|
|
1485
1527
|
];
|
|
1486
1528
|
TBL_QUERIES = {
|
|
1487
1529
|
layer: { name: "layer", lisp: `(progn
|
|
@@ -1528,49 +1570,70 @@ var init_resource_defs = __esm({
|
|
|
1528
1570
|
});
|
|
1529
1571
|
|
|
1530
1572
|
// src/handlers/resource-cache.js
|
|
1573
|
+
function _getCache() {
|
|
1574
|
+
const key = _instanceKey || _defaultKey;
|
|
1575
|
+
if (!_instanceCaches.has(key)) {
|
|
1576
|
+
_instanceCaches.set(key, /* @__PURE__ */ new Map());
|
|
1577
|
+
}
|
|
1578
|
+
return _instanceCaches.get(key);
|
|
1579
|
+
}
|
|
1580
|
+
function _ttl() {
|
|
1581
|
+
return config_default.resourceCacheTtl;
|
|
1582
|
+
}
|
|
1531
1583
|
function ensureCleanup() {
|
|
1532
1584
|
if (cleanupTimer) return;
|
|
1533
1585
|
cleanupTimer = setInterval(() => {
|
|
1534
1586
|
const now = Date.now();
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1587
|
+
const ttl = _ttl();
|
|
1588
|
+
for (const cache of _instanceCaches.values()) {
|
|
1589
|
+
for (const [key, entry] of cache) {
|
|
1590
|
+
if (now - entry.timestamp >= ttl) {
|
|
1591
|
+
cache.delete(key);
|
|
1592
|
+
}
|
|
1538
1593
|
}
|
|
1539
1594
|
}
|
|
1540
1595
|
}, CLEANUP_INTERVAL);
|
|
1541
1596
|
cleanupTimer.unref();
|
|
1542
1597
|
}
|
|
1598
|
+
function setInstanceKey(key) {
|
|
1599
|
+
_instanceKey = key || null;
|
|
1600
|
+
}
|
|
1543
1601
|
function getCached(key) {
|
|
1544
|
-
const
|
|
1545
|
-
|
|
1602
|
+
const cache = _getCache();
|
|
1603
|
+
const entry = cache.get(key);
|
|
1604
|
+
if (entry && Date.now() - entry.timestamp < _ttl()) {
|
|
1546
1605
|
return entry.data;
|
|
1547
1606
|
}
|
|
1548
|
-
|
|
1607
|
+
cache.delete(key);
|
|
1549
1608
|
return null;
|
|
1550
1609
|
}
|
|
1551
1610
|
function setCache(key, data) {
|
|
1552
|
-
|
|
1611
|
+
_getCache().set(key, { data, timestamp: Date.now() });
|
|
1553
1612
|
}
|
|
1554
1613
|
function clearCache(uri) {
|
|
1555
|
-
const
|
|
1556
|
-
if (
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1614
|
+
const basePrefix = URI_CACHE_PREFIX[uri];
|
|
1615
|
+
if (basePrefix) {
|
|
1616
|
+
const cache = _getCache();
|
|
1617
|
+
for (const key of cache.keys()) {
|
|
1618
|
+
if (key === basePrefix || key.startsWith(basePrefix + ":")) {
|
|
1619
|
+
cache.delete(key);
|
|
1560
1620
|
}
|
|
1561
1621
|
}
|
|
1562
1622
|
} else if (!uri) {
|
|
1563
|
-
|
|
1623
|
+
const key = _instanceKey || _defaultKey;
|
|
1624
|
+
_instanceCaches.delete(key);
|
|
1625
|
+
_instanceCaches.set(key, /* @__PURE__ */ new Map());
|
|
1564
1626
|
}
|
|
1565
1627
|
}
|
|
1566
|
-
var
|
|
1628
|
+
var CLEANUP_INTERVAL, cleanupTimer, _instanceKey, _instanceCaches, _defaultKey, URI_CACHE_PREFIX;
|
|
1567
1629
|
var init_resource_cache = __esm({
|
|
1568
1630
|
"src/handlers/resource-cache.js"() {
|
|
1569
1631
|
init_config();
|
|
1570
|
-
CACHE_TTL = config_default.resourceCacheTtl;
|
|
1571
|
-
resourceCache = /* @__PURE__ */ new Map();
|
|
1572
1632
|
CLEANUP_INTERVAL = 6e4;
|
|
1573
1633
|
cleanupTimer = null;
|
|
1634
|
+
_instanceKey = null;
|
|
1635
|
+
_instanceCaches = /* @__PURE__ */ new Map();
|
|
1636
|
+
_defaultKey = "__default__";
|
|
1574
1637
|
ensureCleanup();
|
|
1575
1638
|
URI_CACHE_PREFIX = {
|
|
1576
1639
|
"atlisp://cad/info": "cad:info",
|
|
@@ -1591,6 +1654,23 @@ function createError(code, details = {}) {
|
|
|
1591
1654
|
const def = ERROR_DEFS[code] || ERROR_DEFS[ERROR_CODES.INTERNAL_ERROR];
|
|
1592
1655
|
return new MCPError(code, def.message, details);
|
|
1593
1656
|
}
|
|
1657
|
+
function toMcpError(error2) {
|
|
1658
|
+
if (error2 instanceof MCPError) return error2;
|
|
1659
|
+
if (error2 instanceof Error) {
|
|
1660
|
+
return new MCPError(ERROR_CODES.INTERNAL_ERROR, error2.message, { stack: error2.stack });
|
|
1661
|
+
}
|
|
1662
|
+
return new MCPError(ERROR_CODES.INTERNAL_ERROR, String(error2));
|
|
1663
|
+
}
|
|
1664
|
+
function mcpErrorResponse(error2) {
|
|
1665
|
+
const mcpErr = toMcpError(error2);
|
|
1666
|
+
const json = mcpErr.toJSON();
|
|
1667
|
+
return {
|
|
1668
|
+
content: [{ type: "text", text: `[${json.code}] ${json.message}
|
|
1669
|
+
\u63D0\u793A: ${json.hint}
|
|
1670
|
+
\u5EFA\u8BAE\u5DE5\u5177: ${json.suggestedTools.join(", ") || "\u65E0"}` }],
|
|
1671
|
+
isError: true
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1594
1674
|
function mcpSuccessResponse(text) {
|
|
1595
1675
|
return { content: [{ type: "text", text: String(text) }] };
|
|
1596
1676
|
}
|
|
@@ -1604,9 +1684,14 @@ var init_errors = __esm({
|
|
|
1604
1684
|
LISP_PAREN_MISMATCH: "LISP_PAREN_MISMATCH",
|
|
1605
1685
|
TIMEOUT: "TIMEOUT",
|
|
1606
1686
|
INVALID_PARAMS: "INVALID_PARAMS",
|
|
1687
|
+
INVALID_ARGS: "INVALID_ARGS",
|
|
1607
1688
|
METHOD_NOT_FOUND: "METHOD_NOT_FOUND",
|
|
1689
|
+
HANDLER_NOT_FOUND: "HANDLER_NOT_FOUND",
|
|
1608
1690
|
RESOURCE_NOT_FOUND: "RESOURCE_NOT_FOUND",
|
|
1609
1691
|
PACKAGE_NOT_FOUND: "PACKAGE_NOT_FOUND",
|
|
1692
|
+
OPERATION_FAILED: "OPERATION_FAILED",
|
|
1693
|
+
RATE_LIMITED: "RATE_LIMITED",
|
|
1694
|
+
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
1610
1695
|
INTERNAL_ERROR: "INTERNAL_ERROR"
|
|
1611
1696
|
};
|
|
1612
1697
|
ERROR_DEFS = {
|
|
@@ -1640,6 +1725,31 @@ var init_errors = __esm({
|
|
|
1640
1725
|
hint: "\u8BF7\u68C0\u67E5\u5DE5\u5177\u53C2\u6570\u683C\u5F0F\u662F\u5426\u6B63\u786E\u3002\u4F7F\u7528 search_tools \u6216 list_tools_by_category \u67E5\u770B\u5DE5\u5177\u53C2\u6570\u8981\u6C42",
|
|
1641
1726
|
tools: ["search_tools", "list_tools_by_category"]
|
|
1642
1727
|
},
|
|
1728
|
+
[ERROR_CODES.INVALID_ARGS]: {
|
|
1729
|
+
message: "\u53C2\u6570\u6821\u9A8C\u5931\u8D25",
|
|
1730
|
+
hint: "\u5DE5\u5177\u6240\u9700\u53C2\u6570\u7F3A\u5931\u6216\u683C\u5F0F\u9519\u8BEF\u3002\u8BF7\u68C0\u67E5\u53C2\u6570\u7C7B\u578B\u548C\u5FC5\u586B\u5B57\u6BB5\uFF0C\u4F7F\u7528 search_tools \u67E5\u770B\u5DE5\u5177\u53C2\u6570\u8981\u6C42",
|
|
1731
|
+
tools: ["search_tools", "list_tools_by_category"]
|
|
1732
|
+
},
|
|
1733
|
+
[ERROR_CODES.HANDLER_NOT_FOUND]: {
|
|
1734
|
+
message: "\u5DE5\u5177\u672A\u627E\u5230",
|
|
1735
|
+
hint: "\u5DE5\u5177\u540D\u79F0\u4E0D\u5B58\u5728\u3002\u4F7F\u7528 search_tools \u641C\u7D22\u53EF\u7528\u5DE5\u5177\uFF0C\u6216 list_tools_by_category \u6D4F\u89C8\u5168\u90E8\u5206\u7C7B",
|
|
1736
|
+
tools: ["search_tools", "list_tools_by_category"]
|
|
1737
|
+
},
|
|
1738
|
+
[ERROR_CODES.OPERATION_FAILED]: {
|
|
1739
|
+
message: "\u64CD\u4F5C\u6267\u884C\u5931\u8D25",
|
|
1740
|
+
hint: "\u5DE5\u5177\u6267\u884C\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF\u3002\u53EF\u91CD\u8BD5\u64CD\u4F5C\uFF0C\u6216\u68C0\u67E5\u65E5\u5FD7\u83B7\u53D6\u8BE6\u7EC6\u4FE1\u606F",
|
|
1741
|
+
tools: ["get_system_status", "get_cad_info"]
|
|
1742
|
+
},
|
|
1743
|
+
[ERROR_CODES.RATE_LIMITED]: {
|
|
1744
|
+
message: "\u8C03\u7528\u9891\u7387\u8D85\u9650",
|
|
1745
|
+
hint: "\u5DE5\u5177\u8C03\u7528\u8FC7\u4E8E\u9891\u7E41\u3002\u8BF7\u7B49\u5F85\u4E00\u6BB5\u65F6\u95F4\u540E\u518D\u8BD5",
|
|
1746
|
+
tools: []
|
|
1747
|
+
},
|
|
1748
|
+
[ERROR_CODES.SESSION_NOT_FOUND]: {
|
|
1749
|
+
message: "\u4F1A\u8BDD\u672A\u627E\u5230",
|
|
1750
|
+
hint: "\u6307\u5B9A ID \u7684\u4F1A\u8BDD\u4E0D\u5B58\u5728\u3002\u8BF7\u68C0\u67E5 sessionId \u53C2\u6570\u662F\u5426\u6B63\u786E",
|
|
1751
|
+
tools: ["lisp_repl_list"]
|
|
1752
|
+
},
|
|
1643
1753
|
[ERROR_CODES.METHOD_NOT_FOUND]: {
|
|
1644
1754
|
message: "\u65B9\u6CD5\u4E0D\u5B58\u5728",
|
|
1645
1755
|
hint: "\u5DE5\u5177\u540D\u79F0\u8F93\u5165\u9519\u8BEF\u3002\u4F7F\u7528 search_tools \u641C\u7D22\u53EF\u7528\u5DE5\u5177\uFF0C\u6216 list_tools_by_category \u6D4F\u89C8\u5168\u90E8\u5206\u7C7B",
|
|
@@ -1784,8 +1894,8 @@ __export(renderer_exports, {
|
|
|
1784
1894
|
renderPrompt: () => renderPrompt,
|
|
1785
1895
|
renderTemplate: () => renderTemplate
|
|
1786
1896
|
});
|
|
1787
|
-
function resolvePath(obj,
|
|
1788
|
-
const parts =
|
|
1897
|
+
function resolvePath(obj, path21) {
|
|
1898
|
+
const parts = path21.split(/[.\[\]]/g).filter(Boolean);
|
|
1789
1899
|
let val = obj;
|
|
1790
1900
|
for (const p of parts) {
|
|
1791
1901
|
if (val == null) return void 0;
|
|
@@ -1795,8 +1905,8 @@ function resolvePath(obj, path20) {
|
|
|
1795
1905
|
}
|
|
1796
1906
|
function renderTemplate(template, args) {
|
|
1797
1907
|
return template.replace(PARAM_RE, (match, rawExpr, expr) => {
|
|
1798
|
-
const
|
|
1799
|
-
const val = resolvePath(args,
|
|
1908
|
+
const path21 = rawExpr || expr;
|
|
1909
|
+
const val = resolvePath(args, path21);
|
|
1800
1910
|
if (val == null) return "";
|
|
1801
1911
|
const strVal = String(val);
|
|
1802
1912
|
if (rawExpr) return strVal;
|
|
@@ -2228,8 +2338,8 @@ var init_sse_session = __esm({
|
|
|
2228
2338
|
sendMessage(data) {
|
|
2229
2339
|
return this.sendEvent(SSE_EVENTS.MESSAGE, data);
|
|
2230
2340
|
}
|
|
2231
|
-
sendEndpoint(
|
|
2232
|
-
return this.sendEvent(SSE_EVENTS.ENDPOINT,
|
|
2341
|
+
sendEndpoint(path21) {
|
|
2342
|
+
return this.sendEvent(SSE_EVENTS.ENDPOINT, path21);
|
|
2233
2343
|
}
|
|
2234
2344
|
sendError(code, message, id = null) {
|
|
2235
2345
|
return this.sendEvent(SSE_EVENTS.ERROR, { code, message }, id);
|
|
@@ -2951,7 +3061,8 @@ var init_info_tools = __esm({
|
|
|
2951
3061
|
}
|
|
2952
3062
|
},
|
|
2953
3063
|
{ name: "search_tools", description: "\u6309\u5173\u952E\u8BCD\u641C\u7D22\u53EF\u7528\u5DE5\u5177", inputSchema: { type: "object", properties: { query: { type: "string", description: "\u641C\u7D22\u5173\u952E\u8BCD(\u5339\u914D\u540D\u79F0\u548C\u63CF\u8FF0)" } }, required: ["query"] } },
|
|
2954
|
-
{ name: "list_tools_by_category", description: "\u6309\u5206\u7C7B\u5217\u51FA\u5DE5\u5177", inputSchema: { type: "object", properties: { category: { type: "string", description: "\u5206\u7C7B\u540D\u79F0(\u53EF\u9009,\u4E0D\u4F20\u5219\u5217\u51FA\u6240\u6709\u5206\u7C7B)" } } } }
|
|
3064
|
+
{ name: "list_tools_by_category", description: "\u6309\u5206\u7C7B\u5217\u51FA\u5DE5\u5177", inputSchema: { type: "object", properties: { category: { type: "string", description: "\u5206\u7C7B\u540D\u79F0(\u53EF\u9009,\u4E0D\u4F20\u5219\u5217\u51FA\u6240\u6709\u5206\u7C7B)" } } } },
|
|
3065
|
+
{ name: "get_tool_info", description: "\u83B7\u53D6\u5DE5\u5177\u7684\u8BE6\u7EC6\u4FE1\u606F\uFF08\u53C2\u6570\u3001\u5206\u7C7B\u3001\u53EA\u8BFB/\u7834\u574F\u6027\u6807\u8BB0\u7B49\uFF09", inputSchema: { type: "object", properties: { name: { type: "string", description: "\u5DE5\u5177\u540D\u79F0" } }, required: ["name"] } }
|
|
2955
3066
|
];
|
|
2956
3067
|
}
|
|
2957
3068
|
});
|
|
@@ -5492,12 +5603,12 @@ var init_pool_tools = __esm({
|
|
|
5492
5603
|
inputSchema: {
|
|
5493
5604
|
type: "object",
|
|
5494
5605
|
properties: {
|
|
5495
|
-
key: { type: "string", description: "\u5B9E\u4F8B\u6807\u8BC6\u952E\u540D\uFF08\u5982 autocad, zwcad, mycad\uFF09" },
|
|
5606
|
+
key: { type: "string", description: "\u5B9E\u4F8B\u6807\u8BC6\u952E\u540D\uFF08\u5982 autocad, zwcad, mycad\uFF1B\u4E0D\u4F20\u65F6\u7531 pid \u81EA\u52A8\u6D3E\u751F\uFF09" },
|
|
5496
5607
|
platform: { type: "string", description: "CAD \u5E73\u53F0: AutoCAD, ZWCAD, GStarCAD, BricsCAD\uFF08\u53EF\u9009\uFF0C\u81EA\u52A8\u68C0\u6D4B\uFF09" },
|
|
5608
|
+
pid: { type: "number", description: "\u76EE\u6807\u8FDB\u7A0B PID\uFF08\u53EF\u9009\uFF0C\u901A\u8FC7 ROT \u67E5\u627E\u540E\u8FDE\u63A5\uFF0C\u53EF\u4E0E pid \u81EA\u52A8\u6D3E\u751F key\uFF09" },
|
|
5497
5609
|
label: { type: "string", description: "\u5B9E\u4F8B\u663E\u793A\u6807\u7B7E\uFF08\u53EF\u9009\uFF09" },
|
|
5498
5610
|
makeActive: { type: "boolean", description: "\u8FDE\u63A5\u540E\u8BBE\u4E3A\u6D3B\u52A8\u5B9E\u4F8B\uFF08\u9ED8\u8BA4 true\uFF09" }
|
|
5499
|
-
}
|
|
5500
|
-
required: ["key"]
|
|
5611
|
+
}
|
|
5501
5612
|
}
|
|
5502
5613
|
},
|
|
5503
5614
|
{
|
|
@@ -6457,7 +6568,66 @@ var init_debug_tools = __esm({
|
|
|
6457
6568
|
}
|
|
6458
6569
|
});
|
|
6459
6570
|
|
|
6571
|
+
// src/tools/concurrent-tools.js
|
|
6572
|
+
var tools42;
|
|
6573
|
+
var init_concurrent_tools = __esm({
|
|
6574
|
+
"src/tools/concurrent-tools.js"() {
|
|
6575
|
+
tools42 = [
|
|
6576
|
+
{
|
|
6577
|
+
name: "batch_concurrent_tasks",
|
|
6578
|
+
description: "\u5E76\u53D1\u6267\u884C\u591A\u5B9E\u4F8B\u5DE5\u5177 \u2014 \u5C06\u591A\u4E2A\u5DE5\u5177\u8C03\u7528\u540C\u65F6\u8DEF\u7531\u5230\u4E0D\u540C CAD \u5B9E\u4F8B\u5E76\u884C\u6267\u884C\u3002\u5185\u90E8\u4F7F\u7528 Promise.allSettled\uFF0C\u4E00\u4E2A\u5931\u8D25\u4E0D\u5F71\u54CD\u5176\u4ED6\u3002",
|
|
6579
|
+
inputSchema: {
|
|
6580
|
+
type: "object",
|
|
6581
|
+
properties: {
|
|
6582
|
+
tasks: {
|
|
6583
|
+
type: "array",
|
|
6584
|
+
items: {
|
|
6585
|
+
type: "object",
|
|
6586
|
+
properties: {
|
|
6587
|
+
tool: { type: "string", description: "\u5DE5\u5177\u540D\u79F0" },
|
|
6588
|
+
args: { type: "object", description: "\u5DE5\u5177\u53C2\u6570\uFF08\u4E0D\u542B instance\uFF09" },
|
|
6589
|
+
instance: { type: "string", description: "\u76EE\u6807\u5B9E\u4F8B key" }
|
|
6590
|
+
},
|
|
6591
|
+
required: ["tool", "instance"]
|
|
6592
|
+
},
|
|
6593
|
+
description: "\u8981\u5E76\u53D1\u6267\u884C\u7684\u4EFB\u52A1\u5217\u8868"
|
|
6594
|
+
}
|
|
6595
|
+
},
|
|
6596
|
+
required: ["tasks"]
|
|
6597
|
+
}
|
|
6598
|
+
}
|
|
6599
|
+
];
|
|
6600
|
+
}
|
|
6601
|
+
});
|
|
6602
|
+
|
|
6460
6603
|
// src/tools/index.js
|
|
6604
|
+
function getToolCategory(name) {
|
|
6605
|
+
const n = name;
|
|
6606
|
+
if (/^(draw_|create_3d_|create_box|create_cone|create_cylinder|create_sphere|create_torus|create_wedge|extrude_|revolve_|boolean_|slice_solid|thicken_|offset_surface|create_loft_|create_region)/.test(n)) return "\u7ED8\u56FE\u4E0E3D";
|
|
6607
|
+
if (/^(move_|copy_|rotate_|scale_|mirror_|offset_|array_|batch_)/.test(n)) return "\u4FEE\u6539";
|
|
6608
|
+
if (/^(trim_|extend_|fillet|chamfer|break_|join_|stretch)/.test(n)) return "\u7F16\u8F91";
|
|
6609
|
+
if (/^(create_layer|delete_layer|set_layer|layer_)/.test(n)) return "\u56FE\u5C42";
|
|
6610
|
+
if (/^(create_block|insert_block|explode_block|get_block|set_block|batch_get_block|batch_set_block)/.test(n)) return "\u5757";
|
|
6611
|
+
if (/^(create_dim|list_dim|set_dim|create_hatch|set_hatch)/.test(n)) return "\u6807\u6CE8\u4E0E\u586B\u5145";
|
|
6612
|
+
if (/^(create_ucs|set_ucs|delete_ucs|list_ucs|get_current_ucs|create_layout|delete_layout|rename_layout|set_layout|list_layouts|get_current_layout)/.test(n)) return "\u5750\u6807\u7CFB\u4E0E\u5E03\u5C40";
|
|
6613
|
+
if (/^(create_viewport|set_viewport|lock_viewport|unlock_viewport|maximize_viewport)/.test(n)) return "\u89C6\u53E3";
|
|
6614
|
+
if (/^find_/.test(n)) return "\u7A7A\u95F4\u67E5\u8BE2";
|
|
6615
|
+
if (/^(select_|get_entity|set_entity|delete_entity|get_bounding_box)/.test(n)) return "\u9009\u62E9\u4E0E\u5C5E\u6027";
|
|
6616
|
+
if (/^(open_dwg|save_dwg|export_|import_|close_dwg|publish_)/.test(n)) return "\u6587\u4EF6";
|
|
6617
|
+
if (/^(plot_|save_pdf|batch_plot|publish_layouts)/.test(n)) return "\u6253\u5370";
|
|
6618
|
+
if (/^(get_xdata|set_xdata|delete_xdata|list_xdata|copxy_xdata|search_by_xdata|export_xdata|import_xdata)/.test(n)) return "\u6269\u5C55\u6570\u636E";
|
|
6619
|
+
if (/^(create_sheet|open_sheet|list_sheet|add_sheet|delete_sheet|publish_sheet|sheet_|reorder_sheet|create_subset|list_subset|set_sheet)/.test(n)) return "\u56FE\u7EB8\u96C6";
|
|
6620
|
+
if (/^(attach_|detach_|reload_|list_attached|get_pdf|create_dgn|create_dwf|import_dxf|import_dgn|export_dgn|create_hyper|remove_hyper|xref|bind_xref|clip_xref|path_xref)/.test(n)) return "\u53C2\u7167\u4E0E\u5E95\u56FE";
|
|
6621
|
+
if (/^(create_text|create_mleader|create_linetype|list_text|list_linetype|list_mleader|load_linetype|create_dimension_style|set_dimstyle|list_dimension_styles|set_mleader_style)/.test(n)) return "\u6837\u5F0F";
|
|
6622
|
+
if (/^(purge_|drawing_audit|drawing_recover|overkill)/.test(n)) return "\u6E05\u7406";
|
|
6623
|
+
if (/^(find_text|replace_text|set_text_|justify_|convert_text|explode_text)/.test(n)) return "\u6587\u5B57";
|
|
6624
|
+
if (/^(eval_lisp|connect_cad|get_cad|get_platform|get_system|at_command|new_document|bring_to_front|install_atlisp|init_atlisp|get_system_status)/.test(n)) return "\u7CFB\u7EDF";
|
|
6625
|
+
if (/^(list_packages|search_packages|install_package|get_function_usage|list_symbols|import_funlib)/.test(n)) return "\u5305\u4E0E\u51FD\u6570";
|
|
6626
|
+
if (/^(watch_|lisp_repl|webhook_|sandbox_|audit_|cad_pool_|external_|list_data|export_to|import_external)/.test(n)) return "\u9AD8\u7EA7";
|
|
6627
|
+
if (/^(list_prompts|get_prompt|search_tools|list_tools_by_category|get_tool_info)/.test(n)) return "\u5143\u5DE5\u5177";
|
|
6628
|
+
if (/^(agent_)/.test(n)) return "Agent\u4E0A\u4E0B\u6587";
|
|
6629
|
+
return "\u5176\u4ED6";
|
|
6630
|
+
}
|
|
6461
6631
|
function addAnnotations(tool) {
|
|
6462
6632
|
const isDeprecated = DEPRECATED_TOOLS.has(tool.name);
|
|
6463
6633
|
const isPoolTool = tool.name.startsWith("cad_pool_") || tool.name === "session_pin_instance" || tool.name === "session_unpin_instance";
|
|
@@ -6477,11 +6647,12 @@ function addAnnotations(tool) {
|
|
|
6477
6647
|
destructiveHint: tool.name.startsWith("delete_") || tool.name.startsWith("purge_") || tool.name.startsWith("boolean_") || EXTRA_DESTRUCTIVE.has(tool.name),
|
|
6478
6648
|
idempotentHint: READ_ONLY_TOOLS.has(tool.name) || IDEMPOTENT_WRITE_TOOLS.has(tool.name),
|
|
6479
6649
|
openWorldHint: OPEN_WORLD_TOOLS.has(tool.name),
|
|
6650
|
+
category: getToolCategory(tool.name),
|
|
6480
6651
|
...isDeprecated ? { deprecatedReason: "This tool has been superseded. Check documentation for alternatives." } : {}
|
|
6481
6652
|
}
|
|
6482
6653
|
};
|
|
6483
6654
|
}
|
|
6484
|
-
var READ_ONLY_TOOLS, DEPRECATED_TOOLS, EXTRA_DESTRUCTIVE, IDEMPOTENT_WRITE_TOOLS, OPEN_WORLD_TOOLS,
|
|
6655
|
+
var READ_ONLY_TOOLS, DEPRECATED_TOOLS, EXTRA_DESTRUCTIVE, IDEMPOTENT_WRITE_TOOLS, OPEN_WORLD_TOOLS, tools43, toolsByName;
|
|
6485
6656
|
var init_tools = __esm({
|
|
6486
6657
|
"src/tools/index.js"() {
|
|
6487
6658
|
init_cad_tools();
|
|
@@ -6525,6 +6696,7 @@ var init_tools = __esm({
|
|
|
6525
6696
|
init_batch_transaction_tools();
|
|
6526
6697
|
init_lint_tools();
|
|
6527
6698
|
init_debug_tools();
|
|
6699
|
+
init_concurrent_tools();
|
|
6528
6700
|
READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
6529
6701
|
"get_cad_info",
|
|
6530
6702
|
"get_platform_info",
|
|
@@ -6664,7 +6836,7 @@ var init_tools = __esm({
|
|
|
6664
6836
|
"import_page_setup",
|
|
6665
6837
|
"load_linetype"
|
|
6666
6838
|
]);
|
|
6667
|
-
|
|
6839
|
+
tools43 = [
|
|
6668
6840
|
...tools,
|
|
6669
6841
|
...tools2,
|
|
6670
6842
|
...tools3,
|
|
@@ -6705,9 +6877,10 @@ var init_tools = __esm({
|
|
|
6705
6877
|
...tools39,
|
|
6706
6878
|
...tools37,
|
|
6707
6879
|
...tools40,
|
|
6708
|
-
...tools41
|
|
6880
|
+
...tools41,
|
|
6881
|
+
...tools42
|
|
6709
6882
|
].map(addAnnotations);
|
|
6710
|
-
toolsByName = new Map(
|
|
6883
|
+
toolsByName = new Map(tools43.map((t) => [t.name, t]));
|
|
6711
6884
|
}
|
|
6712
6885
|
});
|
|
6713
6886
|
|
|
@@ -6760,7 +6933,7 @@ function parseLispList(str) {
|
|
|
6760
6933
|
});
|
|
6761
6934
|
}
|
|
6762
6935
|
function createMcpServer(handlers = {}) {
|
|
6763
|
-
const { tools:
|
|
6936
|
+
const { tools: tools44 = [], handleToolCall: handleToolCall2 = () => ({ content: [] }) } = handlers;
|
|
6764
6937
|
const server = new Server(
|
|
6765
6938
|
{ name: SERVER_NAME, version: SERVER_VERSION },
|
|
6766
6939
|
{
|
|
@@ -6783,8 +6956,8 @@ function createMcpServer(handlers = {}) {
|
|
|
6783
6956
|
const params = request.params || {};
|
|
6784
6957
|
const cursor = decodeCursor(params.cursor);
|
|
6785
6958
|
const PAGE_SIZE = 100;
|
|
6786
|
-
const page =
|
|
6787
|
-
const nextCursor = cursor + PAGE_SIZE <
|
|
6959
|
+
const page = tools44.slice(cursor, cursor + PAGE_SIZE);
|
|
6960
|
+
const nextCursor = cursor + PAGE_SIZE < tools44.length ? encodeCursor(cursor + PAGE_SIZE) : void 0;
|
|
6788
6961
|
return { tools: page, nextCursor };
|
|
6789
6962
|
});
|
|
6790
6963
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -7133,11 +7306,11 @@ function createMcpServer(handlers = {}) {
|
|
|
7133
7306
|
if (p.toLowerCase().startsWith(prefix)) values.push(p);
|
|
7134
7307
|
}
|
|
7135
7308
|
} else if (ref?.type === "tool") {
|
|
7136
|
-
for (const t of
|
|
7309
|
+
for (const t of tools44) {
|
|
7137
7310
|
if (t.name.toLowerCase().startsWith(prefix)) values.push(t.name);
|
|
7138
7311
|
}
|
|
7139
7312
|
} else if (ref?.type === "ref/parameter") {
|
|
7140
|
-
const toolDef =
|
|
7313
|
+
const toolDef = tools44.find((t) => t.name === ref.name);
|
|
7141
7314
|
if (toolDef?.inputSchema?.properties) {
|
|
7142
7315
|
const paramName = argument.name;
|
|
7143
7316
|
const paramDef = toolDef.inputSchema.properties[paramName];
|
|
@@ -8361,6 +8534,7 @@ __export(cad_handlers_exports, {
|
|
|
8361
8534
|
newDocument: () => newDocument,
|
|
8362
8535
|
setSystemVariable: () => setSystemVariable
|
|
8363
8536
|
});
|
|
8537
|
+
import iconv from "iconv-lite";
|
|
8364
8538
|
async function connectCad(platform = null) {
|
|
8365
8539
|
log(`connect_cad called${platform ? ` (target: ${platform})` : ""}, cad.connected before: ${cad.connected}`);
|
|
8366
8540
|
try {
|
|
@@ -8443,9 +8617,15 @@ var init_cad_handlers = __esm({
|
|
|
8443
8617
|
${detail}`);
|
|
8444
8618
|
}
|
|
8445
8619
|
if (withResult) {
|
|
8446
|
-
const
|
|
8447
|
-
|
|
8448
|
-
|
|
8620
|
+
const useRaw = encoding ? true : false;
|
|
8621
|
+
const resp = await cad.sendCommandWithResult(trimmed, encoding, useRaw);
|
|
8622
|
+
if (resp !== null) {
|
|
8623
|
+
if (useRaw && resp.rawBase64) {
|
|
8624
|
+
const buf = Buffer.from(resp.rawBase64, "base64");
|
|
8625
|
+
const decoded = iconv.decode(buf, encoding);
|
|
8626
|
+
return mcpSuccess(decoded);
|
|
8627
|
+
}
|
|
8628
|
+
return mcpSuccess(resp);
|
|
8449
8629
|
}
|
|
8450
8630
|
return mcpError("\u6267\u884C\u5931\u8D25\u6216\u65E0\u8FD4\u56DE\u503C");
|
|
8451
8631
|
}
|
|
@@ -10670,6 +10850,87 @@ var init_lint_handlers = __esm({
|
|
|
10670
10850
|
}
|
|
10671
10851
|
});
|
|
10672
10852
|
|
|
10853
|
+
// src/handlers/meta-handlers.js
|
|
10854
|
+
var meta_handlers_exports = {};
|
|
10855
|
+
__export(meta_handlers_exports, {
|
|
10856
|
+
get_prompt_handler: () => get_prompt_handler,
|
|
10857
|
+
get_tool_info: () => get_tool_info,
|
|
10858
|
+
list_prompts_handler: () => list_prompts_handler,
|
|
10859
|
+
list_tools_by_category: () => list_tools_by_category,
|
|
10860
|
+
search_tools: () => search_tools
|
|
10861
|
+
});
|
|
10862
|
+
async function search_tools(a) {
|
|
10863
|
+
const q = (a.query || "").toLowerCase();
|
|
10864
|
+
const results = tools43.filter((t) => t.name.toLowerCase().includes(q) || (t.description || "").toLowerCase().includes(q));
|
|
10865
|
+
const text = results.length ? `\u627E\u5230 ${results.length} \u4E2A\u5DE5\u5177:
|
|
10866
|
+
${results.map((t) => `${t.name}: ${t.description}`).join("\n")}` : `\u672A\u627E\u5230\u5305\u542B "${a.query}" \u7684\u5DE5\u5177`;
|
|
10867
|
+
return { content: [{ type: "text", text }] };
|
|
10868
|
+
}
|
|
10869
|
+
async function list_tools_by_category(a) {
|
|
10870
|
+
const categories = {};
|
|
10871
|
+
for (const t of tools43) {
|
|
10872
|
+
const cat = t.annotations?.category || "\u5176\u4ED6";
|
|
10873
|
+
if (!categories[cat]) categories[cat] = [];
|
|
10874
|
+
categories[cat].push(t.name);
|
|
10875
|
+
}
|
|
10876
|
+
if (a.category) {
|
|
10877
|
+
const names = categories[a.category];
|
|
10878
|
+
return { content: [{ type: "text", text: names ? `${a.category} (${names.length}):
|
|
10879
|
+
${names.join("\n")}` : `\u672A\u627E\u5230\u5206\u7C7B: ${a.category}` }] };
|
|
10880
|
+
}
|
|
10881
|
+
const lines = [];
|
|
10882
|
+
for (const [cat, names] of Object.entries(categories)) {
|
|
10883
|
+
lines.push(`## ${cat} (${names.length})`);
|
|
10884
|
+
}
|
|
10885
|
+
lines.push(`
|
|
10886
|
+
\u5171 ${Object.keys(categories).length} \u4E2A\u5206\u7C7B`);
|
|
10887
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
10888
|
+
}
|
|
10889
|
+
async function get_tool_info(a) {
|
|
10890
|
+
if (!a.name) return { content: [{ type: "text", text: "\u9700\u8981 name \u53C2\u6570\uFF08\u5DE5\u5177\u540D\u79F0\uFF09" }], isError: true };
|
|
10891
|
+
const tool = tools43.find((t) => t.name === a.name);
|
|
10892
|
+
if (!tool) return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5DE5\u5177: ${a.name}` }], isError: true };
|
|
10893
|
+
const ann = tool.annotations || {};
|
|
10894
|
+
const required = (tool.inputSchema?.required || []).join(", ") || "\u65E0";
|
|
10895
|
+
const props = tool.inputSchema?.properties || {};
|
|
10896
|
+
const params = Object.entries(props).map(([k, v]) => {
|
|
10897
|
+
const req = required.includes(k) ? "\u5FC5\u586B" : "\u53EF\u9009";
|
|
10898
|
+
const desc = v.description || "";
|
|
10899
|
+
return ` ${k} (${req}): ${desc}`;
|
|
10900
|
+
}).join("\n");
|
|
10901
|
+
const lines = [
|
|
10902
|
+
`## ${tool.name}`,
|
|
10903
|
+
`\u63CF\u8FF0: ${tool.description || "\u65E0"}`,
|
|
10904
|
+
`\u5206\u7C7B: ${ann.category || "\u5176\u4ED6"}`,
|
|
10905
|
+
`\u53EA\u8BFB: ${ann.readOnlyHint ? "\u662F" : "\u5426"}`,
|
|
10906
|
+
`\u7834\u574F\u6027: ${ann.destructiveHint ? "\u662F" : "\u5426"}`,
|
|
10907
|
+
`\u5E42\u7B49: ${ann.idempotentHint ? "\u662F" : "\u5426"}`,
|
|
10908
|
+
`\u5F00\u653E\u4E16\u754C: ${ann.openWorldHint ? "\u662F" : "\u5426"}`,
|
|
10909
|
+
``,
|
|
10910
|
+
`\u53C2\u6570:`,
|
|
10911
|
+
params || " \u65E0\u53C2\u6570"
|
|
10912
|
+
];
|
|
10913
|
+
if (ann.deprecatedReason) {
|
|
10914
|
+
lines.push(`
|
|
10915
|
+
\u5DF2\u5F03\u7528: ${ann.deprecatedReason}`);
|
|
10916
|
+
}
|
|
10917
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
10918
|
+
}
|
|
10919
|
+
async function list_prompts_handler() {
|
|
10920
|
+
const prompts = await listPrompts2();
|
|
10921
|
+
return { content: [{ type: "text", text: JSON.stringify(prompts) }] };
|
|
10922
|
+
}
|
|
10923
|
+
async function get_prompt_handler(a) {
|
|
10924
|
+
const prompt = await getPrompt2(a.name, a.args || {});
|
|
10925
|
+
return { content: prompt.messages.map((m) => ({ type: "text", text: m.content.text || m.content })) };
|
|
10926
|
+
}
|
|
10927
|
+
var init_meta_handlers = __esm({
|
|
10928
|
+
"src/handlers/meta-handlers.js"() {
|
|
10929
|
+
init_tools();
|
|
10930
|
+
init_prompt_handlers();
|
|
10931
|
+
}
|
|
10932
|
+
});
|
|
10933
|
+
|
|
10673
10934
|
// src/handlers/package-handlers.js
|
|
10674
10935
|
var package_handlers_exports = {};
|
|
10675
10936
|
__export(package_handlers_exports, {
|
|
@@ -10679,7 +10940,7 @@ __export(package_handlers_exports, {
|
|
|
10679
10940
|
});
|
|
10680
10941
|
async function fetchPackages() {
|
|
10681
10942
|
const now = Date.now();
|
|
10682
|
-
if (cachedPackages && cachedAt2 && now - cachedAt2 <
|
|
10943
|
+
if (cachedPackages && cachedAt2 && now - cachedAt2 < CACHE_TTL) {
|
|
10683
10944
|
return cachedPackages;
|
|
10684
10945
|
}
|
|
10685
10946
|
try {
|
|
@@ -10756,7 +11017,7 @@ async function installPackage(packageName) {
|
|
|
10756
11017
|
}
|
|
10757
11018
|
return { content: [{ type: "text", text: `\u5305 "${packageName}" \u5B89\u88C5\u547D\u4EE4\u5DF2\u53D1\u9001\uFF01` }] };
|
|
10758
11019
|
}
|
|
10759
|
-
var PACKAGES_LIST_URL, cachedPackages, cachedAt2,
|
|
11020
|
+
var PACKAGES_LIST_URL, cachedPackages, cachedAt2, CACHE_TTL;
|
|
10760
11021
|
var init_package_handlers = __esm({
|
|
10761
11022
|
"src/handlers/package-handlers.js"() {
|
|
10762
11023
|
init_logger();
|
|
@@ -10765,7 +11026,7 @@ var init_package_handlers = __esm({
|
|
|
10765
11026
|
PACKAGES_LIST_URL = process.env.PACKAGES_LIST_URL || "http://s3.atlisp.cn/packages-list?fmt=json";
|
|
10766
11027
|
cachedPackages = null;
|
|
10767
11028
|
cachedAt2 = null;
|
|
10768
|
-
|
|
11029
|
+
CACHE_TTL = 10 * 60 * 1e3;
|
|
10769
11030
|
}
|
|
10770
11031
|
});
|
|
10771
11032
|
|
|
@@ -12589,6 +12850,192 @@ var init_sheetset_handlers = __esm({
|
|
|
12589
12850
|
}
|
|
12590
12851
|
});
|
|
12591
12852
|
|
|
12853
|
+
// src/handlers/skill-handlers.js
|
|
12854
|
+
var skill_handlers_exports = {};
|
|
12855
|
+
__export(skill_handlers_exports, {
|
|
12856
|
+
skill_install: () => skill_install,
|
|
12857
|
+
skill_list_categories: () => skill_list_categories,
|
|
12858
|
+
skill_list_installed: () => skill_list_installed,
|
|
12859
|
+
skill_search: () => skill_search,
|
|
12860
|
+
skill_uninstall: () => skill_uninstall
|
|
12861
|
+
});
|
|
12862
|
+
import fs8 from "fs";
|
|
12863
|
+
import path12 from "path";
|
|
12864
|
+
import os7 from "os";
|
|
12865
|
+
function readCache() {
|
|
12866
|
+
try {
|
|
12867
|
+
if (fs8.existsSync(CACHE_PATH)) return JSON.parse(fs8.readFileSync(CACHE_PATH, "utf-8"));
|
|
12868
|
+
} catch {
|
|
12869
|
+
}
|
|
12870
|
+
return null;
|
|
12871
|
+
}
|
|
12872
|
+
function writeCache(data) {
|
|
12873
|
+
try {
|
|
12874
|
+
fs8.writeFileSync(CACHE_PATH, JSON.stringify(data, null, 2), "utf-8");
|
|
12875
|
+
} catch {
|
|
12876
|
+
}
|
|
12877
|
+
}
|
|
12878
|
+
async function fetchIndex() {
|
|
12879
|
+
let index = readCache();
|
|
12880
|
+
if (index && Date.now() - index.fetchedAt < 36e5) return index;
|
|
12881
|
+
try {
|
|
12882
|
+
const resp = await fetch(REGISTRY_URL, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
12883
|
+
if (resp.ok) {
|
|
12884
|
+
index = await resp.json();
|
|
12885
|
+
index.fetchedAt = Date.now();
|
|
12886
|
+
writeCache(index);
|
|
12887
|
+
}
|
|
12888
|
+
} catch {
|
|
12889
|
+
}
|
|
12890
|
+
return index;
|
|
12891
|
+
}
|
|
12892
|
+
async function skill_search(a) {
|
|
12893
|
+
const index = await fetchIndex();
|
|
12894
|
+
if (!index?.skills) return { content: [{ type: "text", text: "\u65E0\u6CD5\u83B7\u53D6 skill \u6CE8\u518C\u8868\u7D22\u5F15" }], isError: true };
|
|
12895
|
+
const q = (a.query || "").toLowerCase();
|
|
12896
|
+
const results = index.skills.filter(
|
|
12897
|
+
(s) => s.name.toLowerCase().includes(q) || (s.description || "").toLowerCase().includes(q) || (s.tags || []).some((t) => t.toLowerCase().includes(q))
|
|
12898
|
+
);
|
|
12899
|
+
if (!results.length) return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5339\u914D "${a.query}" \u7684 skill` }] };
|
|
12900
|
+
const lines = [`\u627E\u5230 ${results.length} \u4E2A skill:
|
|
12901
|
+
`];
|
|
12902
|
+
for (const s of results) {
|
|
12903
|
+
lines.push(`**${s.name}**`);
|
|
12904
|
+
if (s.description) lines.push(` \u63CF\u8FF0: ${s.description}`);
|
|
12905
|
+
if (s.tags?.length) lines.push(` \u6807\u7B7E: ${s.tags.join(", ")}`);
|
|
12906
|
+
if (s.version) lines.push(` \u7248\u672C: ${s.version}`);
|
|
12907
|
+
lines.push("");
|
|
12908
|
+
}
|
|
12909
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
12910
|
+
}
|
|
12911
|
+
async function skill_install(a) {
|
|
12912
|
+
if (!a.name) return { content: [{ type: "text", text: "\u9700\u8981 skill \u540D\u79F0" }], isError: true };
|
|
12913
|
+
const index = await fetchIndex();
|
|
12914
|
+
if (!index?.skills) return { content: [{ type: "text", text: "\u65E0\u6CD5\u83B7\u53D6 skill \u6CE8\u518C\u8868\u7D22\u5F15" }], isError: true };
|
|
12915
|
+
const skill = index.skills.find((s) => s.name === a.name);
|
|
12916
|
+
if (!skill) return { content: [{ type: "text", text: `\u672A\u627E\u5230 skill: ${a.name}` }], isError: true };
|
|
12917
|
+
const downloadUrl = skill.download_url || skill.url;
|
|
12918
|
+
if (!downloadUrl) return { content: [{ type: "text", text: `Skill "${a.name}" \u6CA1\u6709\u4E0B\u8F7D\u5730\u5740` }], isError: true };
|
|
12919
|
+
let content;
|
|
12920
|
+
try {
|
|
12921
|
+
const resp = await fetch(downloadUrl, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
12922
|
+
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
|
12923
|
+
content = await resp.text();
|
|
12924
|
+
} catch (e) {
|
|
12925
|
+
return { content: [{ type: "text", text: `\u4E0B\u8F7D\u5931\u8D25: ${e.message}` }], isError: true };
|
|
12926
|
+
}
|
|
12927
|
+
try {
|
|
12928
|
+
fs8.mkdirSync(SKILLS_DIR, { recursive: true });
|
|
12929
|
+
} catch {
|
|
12930
|
+
}
|
|
12931
|
+
const safeName = a.name.replace(/[^a-zA-Z0-9\u4e00-\u9fff_-]/g, "-").substring(0, 40);
|
|
12932
|
+
const skillFile = path12.join(SKILLS_DIR, `skill-${safeName}.md`);
|
|
12933
|
+
if (fs8.existsSync(skillFile)) {
|
|
12934
|
+
return { content: [{ type: "text", text: `Skill "${a.name}" \u5DF2\u5B89\u88C5 (${skillFile})` }], isError: true };
|
|
12935
|
+
}
|
|
12936
|
+
let finalContent = content;
|
|
12937
|
+
if (!content.match(/^---\n/)) {
|
|
12938
|
+
const tags = (skill.tags || []).join(", ");
|
|
12939
|
+
finalContent = `---
|
|
12940
|
+
name: ${a.name}
|
|
12941
|
+
description: ${skill.description || ""}
|
|
12942
|
+
tags: ${tags}
|
|
12943
|
+
---
|
|
12944
|
+
|
|
12945
|
+
${content}`;
|
|
12946
|
+
}
|
|
12947
|
+
fs8.writeFileSync(skillFile, finalContent, "utf-8");
|
|
12948
|
+
return { content: [{ type: "text", text: `${skill.name} \u5B89\u88C5\u6210\u529F
|
|
12949
|
+
\u6587\u4EF6: ${skillFile}${skill.version ? `
|
|
12950
|
+
\u7248\u672C: ${skill.version}` : ""}` }] };
|
|
12951
|
+
}
|
|
12952
|
+
async function skill_list_installed() {
|
|
12953
|
+
if (!fs8.existsSync(SKILLS_DIR)) return { content: [{ type: "text", text: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684 skill" }] };
|
|
12954
|
+
const results = [];
|
|
12955
|
+
try {
|
|
12956
|
+
const entries = fs8.readdirSync(SKILLS_DIR, { withFileTypes: true });
|
|
12957
|
+
for (const entry of entries) {
|
|
12958
|
+
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
12959
|
+
const fullPath = path12.join(SKILLS_DIR, entry.name);
|
|
12960
|
+
try {
|
|
12961
|
+
const raw = fs8.readFileSync(fullPath, "utf-8");
|
|
12962
|
+
const match = raw.match(/^---\n([\s\S]*?)\n---/);
|
|
12963
|
+
if (match) {
|
|
12964
|
+
const fm = {};
|
|
12965
|
+
for (const line of match[1].split("\n")) {
|
|
12966
|
+
const sep = line.indexOf(":");
|
|
12967
|
+
if (sep > 0) fm[line.slice(0, sep).trim()] = line.slice(sep + 1).trim();
|
|
12968
|
+
}
|
|
12969
|
+
results.push({ name: fm.name || entry.name.replace(".md", ""), description: fm.description || "", tags: fm.tags || "" });
|
|
12970
|
+
} else {
|
|
12971
|
+
results.push({ name: entry.name.replace(".md", ""), description: "", tags: "" });
|
|
12972
|
+
}
|
|
12973
|
+
} catch {
|
|
12974
|
+
}
|
|
12975
|
+
}
|
|
12976
|
+
}
|
|
12977
|
+
} catch {
|
|
12978
|
+
}
|
|
12979
|
+
if (!results.length) return { content: [{ type: "text", text: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684 skill" }] };
|
|
12980
|
+
const lines = [`\u5DF2\u5B89\u88C5 ${results.length} \u4E2A skill:
|
|
12981
|
+
`];
|
|
12982
|
+
for (const s of results) {
|
|
12983
|
+
lines.push(`**${s.name}**${s.description ? ` \u2014 ${s.description}` : ""}`);
|
|
12984
|
+
if (s.tags) lines.push(` \u6807\u7B7E: ${s.tags}`);
|
|
12985
|
+
}
|
|
12986
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
12987
|
+
}
|
|
12988
|
+
async function skill_uninstall(a) {
|
|
12989
|
+
if (!a.name) return { content: [{ type: "text", text: "\u9700\u8981 skill \u540D\u79F0" }], isError: true };
|
|
12990
|
+
if (!fs8.existsSync(SKILLS_DIR)) return { content: [{ type: "text", text: `\u672A\u5B89\u88C5 skill: ${a.name}` }], isError: true };
|
|
12991
|
+
let found = null;
|
|
12992
|
+
try {
|
|
12993
|
+
const entries = fs8.readdirSync(SKILLS_DIR, { withFileTypes: true });
|
|
12994
|
+
for (const entry of entries) {
|
|
12995
|
+
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
12996
|
+
const fullPath = path12.join(SKILLS_DIR, entry.name);
|
|
12997
|
+
try {
|
|
12998
|
+
const raw = fs8.readFileSync(fullPath, "utf-8");
|
|
12999
|
+
const match = raw.match(/^---\n([\s\S]*?)\n---/);
|
|
13000
|
+
if (match) {
|
|
13001
|
+
for (const line of match[1].split("\n")) {
|
|
13002
|
+
if (line.startsWith("name:") && line.slice(5).trim() === a.name) {
|
|
13003
|
+
found = fullPath;
|
|
13004
|
+
break;
|
|
13005
|
+
}
|
|
13006
|
+
}
|
|
13007
|
+
} else if (entry.name.replace(".md", "") === a.name) {
|
|
13008
|
+
found = fullPath;
|
|
13009
|
+
}
|
|
13010
|
+
} catch {
|
|
13011
|
+
}
|
|
13012
|
+
if (found) break;
|
|
13013
|
+
}
|
|
13014
|
+
}
|
|
13015
|
+
} catch {
|
|
13016
|
+
}
|
|
13017
|
+
if (!found) return { content: [{ type: "text", text: `\u672A\u5B89\u88C5 skill: ${a.name}` }], isError: true };
|
|
13018
|
+
fs8.unlinkSync(found);
|
|
13019
|
+
return { content: [{ type: "text", text: `${a.name} \u5DF2\u5378\u8F7D` }] };
|
|
13020
|
+
}
|
|
13021
|
+
async function skill_list_categories() {
|
|
13022
|
+
const index = await fetchIndex();
|
|
13023
|
+
if (!index?.skills) return { content: [{ type: "text", text: "\u65E0\u6CD5\u83B7\u53D6 skill \u6CE8\u518C\u8868\u7D22\u5F15" }], isError: true };
|
|
13024
|
+
const cats = /* @__PURE__ */ new Set();
|
|
13025
|
+
for (const s of index.skills) for (const t of s.tags || []) cats.add(t);
|
|
13026
|
+
const sorted = Array.from(cats).sort();
|
|
13027
|
+
return { content: [{ type: "text", text: sorted.length ? `\u6CE8\u518C\u8868\u5206\u7C7B (${sorted.length}):
|
|
13028
|
+
${sorted.join("\n")}` : "\u6682\u65E0\u5206\u7C7B" }] };
|
|
13029
|
+
}
|
|
13030
|
+
var SKILLS_DIR, REGISTRY_URL, CACHE_PATH;
|
|
13031
|
+
var init_skill_handlers = __esm({
|
|
13032
|
+
"src/handlers/skill-handlers.js"() {
|
|
13033
|
+
SKILLS_DIR = path12.join(os7.homedir(), ".atlisp", "skills");
|
|
13034
|
+
REGISTRY_URL = process.env.SKILL_REGISTRY_URL || "https://raw.githubusercontent.com/atlisp/skill-registry/main/index.json";
|
|
13035
|
+
CACHE_PATH = path12.join(os7.homedir(), ".atlisp", "skill-registry-cache.json");
|
|
13036
|
+
}
|
|
13037
|
+
});
|
|
13038
|
+
|
|
12592
13039
|
// src/handlers/spatial-handlers.js
|
|
12593
13040
|
var spatial_handlers_exports = {};
|
|
12594
13041
|
__export(spatial_handlers_exports, {
|
|
@@ -13960,13 +14407,13 @@ function lispPoint(pt) {
|
|
|
13960
14407
|
}
|
|
13961
14408
|
async function attachXref(args) {
|
|
13962
14409
|
try {
|
|
13963
|
-
const
|
|
14410
|
+
const path21 = esc3(args.path);
|
|
13964
14411
|
const point = lispPoint(args.point);
|
|
13965
14412
|
const scale = args.scale || 1;
|
|
13966
14413
|
const rotation = args.rotation || 0;
|
|
13967
14414
|
const overlay = args.overlay ? "_O" : "_A";
|
|
13968
14415
|
const result = await cad.sendCommandWithResult(
|
|
13969
|
-
`(command "_.XATTACH" "${
|
|
14416
|
+
`(command "_.XATTACH" "${path21}" "${overlay}" "${point}" "${scale}" "${rotation}") (princ)`
|
|
13970
14417
|
);
|
|
13971
14418
|
return mcpSuccess(`\u5916\u90E8\u53C2\u7167\u5DF2\u9644\u7740: ${args.path}`);
|
|
13972
14419
|
} catch (e) {
|
|
@@ -14294,6 +14741,7 @@ var init_ = __esm({
|
|
|
14294
14741
|
"./handlers/function-handlers.js": () => Promise.resolve().then(() => (init_function_handlers(), function_handlers_exports)),
|
|
14295
14742
|
"./handlers/layer-handlers.js": () => Promise.resolve().then(() => (init_layer_handlers(), layer_handlers_exports)),
|
|
14296
14743
|
"./handlers/lint-handlers.js": () => Promise.resolve().then(() => (init_lint_handlers(), lint_handlers_exports)),
|
|
14744
|
+
"./handlers/meta-handlers.js": () => Promise.resolve().then(() => (init_meta_handlers(), meta_handlers_exports)),
|
|
14297
14745
|
"./handlers/package-handlers.js": () => Promise.resolve().then(() => (init_package_handlers(), package_handlers_exports)),
|
|
14298
14746
|
"./handlers/parametric-handlers.js": () => Promise.resolve().then(() => (init_parametric_handlers(), parametric_handlers_exports)),
|
|
14299
14747
|
"./handlers/pdf-annotation-handlers.js": () => Promise.resolve().then(() => (init_pdf_annotation_handlers(), pdf_annotation_handlers_exports)),
|
|
@@ -14302,6 +14750,7 @@ var init_ = __esm({
|
|
|
14302
14750
|
"./handlers/query-print-handlers.js": () => Promise.resolve().then(() => (init_query_print_handlers(), query_print_handlers_exports)),
|
|
14303
14751
|
"./handlers/resource-handlers.js": () => Promise.resolve().then(() => (init_resource_handlers(), resource_handlers_exports)),
|
|
14304
14752
|
"./handlers/sheetset-handlers.js": () => Promise.resolve().then(() => (init_sheetset_handlers(), sheetset_handlers_exports)),
|
|
14753
|
+
"./handlers/skill-handlers.js": () => Promise.resolve().then(() => (init_skill_handlers(), skill_handlers_exports)),
|
|
14305
14754
|
"./handlers/spatial-handlers.js": () => Promise.resolve().then(() => (init_spatial_handlers(), spatial_handlers_exports)),
|
|
14306
14755
|
"./handlers/style-handlers.js": () => Promise.resolve().then(() => (init_style_handlers(), style_handlers_exports)),
|
|
14307
14756
|
"./handlers/text-handlers.js": () => Promise.resolve().then(() => (init_text_handlers(), text_handlers_exports)),
|
|
@@ -14314,8 +14763,8 @@ var init_ = __esm({
|
|
|
14314
14763
|
});
|
|
14315
14764
|
|
|
14316
14765
|
// src/handler-loader.js
|
|
14317
|
-
import
|
|
14318
|
-
import
|
|
14766
|
+
import fs9 from "fs";
|
|
14767
|
+
import path13 from "path";
|
|
14319
14768
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14320
14769
|
function toolNameToFuncName(toolName) {
|
|
14321
14770
|
if (FUNCTION_OVERRIDES[toolName]) return FUNCTION_OVERRIDES[toolName];
|
|
@@ -14365,10 +14814,10 @@ async function getHandlerModule(name) {
|
|
|
14365
14814
|
async function initHandlerModules() {
|
|
14366
14815
|
if (_handlerModulesInit) return;
|
|
14367
14816
|
_handlerModulesInit = true;
|
|
14368
|
-
const handlerDir =
|
|
14817
|
+
const handlerDir = path13.join(__dirname5, "handlers");
|
|
14369
14818
|
let names;
|
|
14370
14819
|
try {
|
|
14371
|
-
names = await
|
|
14820
|
+
names = await fs9.promises.readdir(handlerDir);
|
|
14372
14821
|
} catch {
|
|
14373
14822
|
log("Handler directory not found, using static manifest");
|
|
14374
14823
|
return;
|
|
@@ -14379,6 +14828,7 @@ async function initHandlerModules() {
|
|
|
14379
14828
|
handlerModules[name] = () => globImport_handlers_handlers_js(`./handlers/${name}-handlers.js`);
|
|
14380
14829
|
}
|
|
14381
14830
|
}
|
|
14831
|
+
watchHandlers();
|
|
14382
14832
|
}
|
|
14383
14833
|
async function getHandler(toolName) {
|
|
14384
14834
|
const resolved = await resolveHandler(toolName);
|
|
@@ -14387,12 +14837,40 @@ async function getHandler(toolName) {
|
|
|
14387
14837
|
if (!mod || typeof mod[resolved.funcName] !== "function") return null;
|
|
14388
14838
|
return mod[resolved.funcName];
|
|
14389
14839
|
}
|
|
14390
|
-
|
|
14840
|
+
function watchHandlers() {
|
|
14841
|
+
if (_watcherInitialized) return;
|
|
14842
|
+
_watcherInitialized = true;
|
|
14843
|
+
const handlerDir = path13.join(__dirname5, "handlers");
|
|
14844
|
+
let debounceTimer = null;
|
|
14845
|
+
try {
|
|
14846
|
+
if (!fs9.existsSync(handlerDir)) return;
|
|
14847
|
+
fs9.watch(handlerDir, (eventType, filename) => {
|
|
14848
|
+
if (!filename || !filename.endsWith("-handlers.js")) return;
|
|
14849
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
14850
|
+
debounceTimer = setTimeout(async () => {
|
|
14851
|
+
const name = filename.replace("-handlers.js", "");
|
|
14852
|
+
moduleCache.delete(name);
|
|
14853
|
+
resolvedCache.clear();
|
|
14854
|
+
_handlerNameMapInit = false;
|
|
14855
|
+
_handlerModulesInit = false;
|
|
14856
|
+
try {
|
|
14857
|
+
await initHandlerModules();
|
|
14858
|
+
log(`Handler hot-reloaded: ${filename}`);
|
|
14859
|
+
} catch (e) {
|
|
14860
|
+
log(`Handler reload failed for ${filename}: ${e.message}`);
|
|
14861
|
+
}
|
|
14862
|
+
}, 300);
|
|
14863
|
+
});
|
|
14864
|
+
} catch (e) {
|
|
14865
|
+
log(`Handler watch error: ${e.message}`);
|
|
14866
|
+
}
|
|
14867
|
+
}
|
|
14868
|
+
var __dirname5, _handlerModulesInit, _handlerNameMapInit, handlerModules, moduleCache, resolvedCache, FUNCTION_OVERRIDES, _watcherInitialized;
|
|
14391
14869
|
var init_handler_loader = __esm({
|
|
14392
14870
|
"src/handler-loader.js"() {
|
|
14393
14871
|
init_logger();
|
|
14394
14872
|
init_();
|
|
14395
|
-
__dirname5 =
|
|
14873
|
+
__dirname5 = path13.dirname(fileURLToPath5(import.meta.url));
|
|
14396
14874
|
_handlerModulesInit = false;
|
|
14397
14875
|
_handlerNameMapInit = false;
|
|
14398
14876
|
handlerModules = {};
|
|
@@ -14404,16 +14882,18 @@ var init_handler_loader = __esm({
|
|
|
14404
14882
|
get_dimension: "getDimensionValue",
|
|
14405
14883
|
eval_lisp_with_result: "evalLisp"
|
|
14406
14884
|
};
|
|
14885
|
+
_watcherInitialized = false;
|
|
14407
14886
|
}
|
|
14408
14887
|
});
|
|
14409
14888
|
|
|
14410
14889
|
// src/streaming.js
|
|
14411
|
-
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14416
|
-
const ssgetExpr =
|
|
14890
|
+
function escapeLispStr(str) {
|
|
14891
|
+
if (typeof str !== "string") return "";
|
|
14892
|
+
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
14893
|
+
}
|
|
14894
|
+
async function streamEntities({ filterExpr, extractFields, itemMapper, offset, limit, hasFilter, warnThreshold, overLimitMsg, resultProp }) {
|
|
14895
|
+
const ssgetExpr = filterExpr ? `(ssget "_X" ${filterExpr})` : `(ssget "_X")`;
|
|
14896
|
+
const extractCode = extractFields.length === 1 ? `(list ${extractFields.join(" ")})` : `(list ${extractFields.join(" ")})`;
|
|
14417
14897
|
const lisp = `(progn
|
|
14418
14898
|
(setq ss ${ssgetExpr})
|
|
14419
14899
|
(setq total (if ss (sslength ss) 0))
|
|
@@ -14425,10 +14905,10 @@ async function streamEntitiesByType({ type = null, layer = null, chunk = STREAM_
|
|
|
14425
14905
|
(setq result (list total))
|
|
14426
14906
|
(setq i ${offset})
|
|
14427
14907
|
(setq count 0)
|
|
14428
|
-
(while (and (< i total) (< count ${
|
|
14908
|
+
(while (and (< i total) (< count ${limit}))
|
|
14429
14909
|
(setq e (ssname ss i))
|
|
14430
14910
|
(setq elist (entget e))
|
|
14431
|
-
(setq result (cons
|
|
14911
|
+
(setq result (cons ${extractCode} result))
|
|
14432
14912
|
(setq i (1+ i))
|
|
14433
14913
|
(setq count (1+ count)))
|
|
14434
14914
|
(reverse result)))))`;
|
|
@@ -14442,108 +14922,68 @@ async function streamEntitiesByType({ type = null, layer = null, chunk = STREAM_
|
|
|
14442
14922
|
offset: 0,
|
|
14443
14923
|
count: 0,
|
|
14444
14924
|
hasMore: false,
|
|
14445
|
-
|
|
14446
|
-
error: `\u5B9E\u4F53\u6570\u91CF (${parsed[1]}) \u8D85\u8FC7\u6700\u5927\u9650\u5236 (${MAX_ENTITY_LIMIT})\uFF0C
|
|
14925
|
+
[resultProp]: [],
|
|
14926
|
+
error: `\u5B9E\u4F53\u6570\u91CF (${parsed[1]}) \u8D85\u8FC7\u6700\u5927\u9650\u5236 (${MAX_ENTITY_LIMIT})\uFF0C${overLimitMsg}`
|
|
14447
14927
|
};
|
|
14448
14928
|
}
|
|
14449
|
-
const
|
|
14450
|
-
const result = {
|
|
14451
|
-
|
|
14452
|
-
|
|
14453
|
-
count: entities.length,
|
|
14454
|
-
hasMore: offset + entities.length < total,
|
|
14455
|
-
entities
|
|
14456
|
-
};
|
|
14457
|
-
if (!hasFilter && total > UNFILTERED_WARN_THRESHOLD) {
|
|
14458
|
-
result.warning = `\u672A\u63D0\u4F9B type/layer \u8FC7\u6EE4\uFF0C\u5168\u56FE\u626B\u63CF\u4E86 ${total} \u4E2A\u5B9E\u4F53\u3002\u5EFA\u8BAE\u6DFB\u52A0 type \u6216 layer \u53C2\u6570\u4EE5\u5927\u5E45\u63D0\u5347\u6027\u80FD\u548C\u964D\u4F4E\u5185\u5B58\u5360\u7528\u3002`;
|
|
14929
|
+
const items = parsed.slice(1).map(itemMapper);
|
|
14930
|
+
const result = { total, offset, count: items.length, hasMore: offset + items.length < total, [resultProp]: items };
|
|
14931
|
+
if (!hasFilter && total > warnThreshold) {
|
|
14932
|
+
result.warning = `\u672A\u63D0\u4F9B\u8FC7\u6EE4\u6761\u4EF6\uFF0C\u5168\u56FE\u626B\u63CF\u4E86 ${total} \u4E2A\u5B9E\u4F53\u3002\u5EFA\u8BAE\u6DFB\u52A0\u8FC7\u6EE4\u53C2\u6570\u4EE5\u63D0\u5347\u6027\u80FD\u3002`;
|
|
14459
14933
|
}
|
|
14460
14934
|
return result;
|
|
14461
14935
|
} catch {
|
|
14462
|
-
return { total: 0, offset: 0, count: 0, hasMore: false,
|
|
14936
|
+
return { total: 0, offset: 0, count: 0, hasMore: false, [resultProp]: [] };
|
|
14463
14937
|
}
|
|
14464
14938
|
}
|
|
14939
|
+
async function streamEntitiesByType({ type = null, layer = null, chunk = STREAM_CHUNK_SIZE, offset = 0 }) {
|
|
14940
|
+
const filters = [];
|
|
14941
|
+
if (type) filters.push(`(cons 0 "${escapeLispStr(type)}")`);
|
|
14942
|
+
if (layer) filters.push(`(cons 8 "${escapeLispStr(layer)}")`);
|
|
14943
|
+
const filterExpr = filters.length > 0 ? `(list ${filters.join(" ")})` : null;
|
|
14944
|
+
return streamEntities({
|
|
14945
|
+
filterExpr,
|
|
14946
|
+
extractFields: ["(list (cdr (assoc 0 elist)) (cdr (assoc 5 elist)) (cdr (assoc 8 elist)))"],
|
|
14947
|
+
itemMapper: (item) => ({ type: item[0], handle: item[1], layer: item[2] }),
|
|
14948
|
+
offset,
|
|
14949
|
+
limit: chunk,
|
|
14950
|
+
hasFilter: !!(type || layer),
|
|
14951
|
+
warnThreshold: UNFILTERED_WARN_THRESHOLD,
|
|
14952
|
+
overLimitMsg: "\u8BF7\u4F7F\u7528 type/layer \u8FC7\u6EE4",
|
|
14953
|
+
resultProp: "entities"
|
|
14954
|
+
});
|
|
14955
|
+
}
|
|
14465
14956
|
async function streamTextContent({ layer = null, bbox = null, offset = 0, limit = 100 }) {
|
|
14466
14957
|
const textFilters = [`(cons 0 "TEXT")`, `(cons 0 "MTEXT")`];
|
|
14467
|
-
if (layer) textFilters.push(`(cons 8 "${layer}")`);
|
|
14468
|
-
const
|
|
14469
|
-
|
|
14470
|
-
|
|
14471
|
-
(
|
|
14472
|
-
|
|
14473
|
-
|
|
14474
|
-
|
|
14475
|
-
|
|
14476
|
-
|
|
14477
|
-
|
|
14478
|
-
|
|
14479
|
-
|
|
14480
|
-
(setq e (ssname ss i))
|
|
14481
|
-
(setq elist (entget e))
|
|
14482
|
-
(setq txt (cdr (assoc 1 elist)))
|
|
14483
|
-
(setq result (cons (list (cdr (assoc 5 elist)) txt (cdr (assoc 10 elist))) result))
|
|
14484
|
-
(setq i (1+ i))
|
|
14485
|
-
(setq count (1+ count)))
|
|
14486
|
-
(reverse result)))))`;
|
|
14487
|
-
const raw = await cad.sendCommandWithResult(lisp);
|
|
14488
|
-
try {
|
|
14489
|
-
const parsed = JSON.parse(raw);
|
|
14490
|
-
const total = parsed[0] || 0;
|
|
14491
|
-
if (total === -1) {
|
|
14492
|
-
return {
|
|
14493
|
-
total: parsed[1] || 0,
|
|
14494
|
-
offset: 0,
|
|
14495
|
-
count: 0,
|
|
14496
|
-
hasMore: false,
|
|
14497
|
-
texts: [],
|
|
14498
|
-
error: `\u6587\u672C\u5B9E\u4F53\u6570\u91CF (${parsed[1]}) \u8D85\u8FC7\u6700\u5927\u9650\u5236 (${MAX_ENTITY_LIMIT})\uFF0C\u8BF7\u4F7F\u7528 layer \u8FC7\u6EE4`
|
|
14499
|
-
};
|
|
14500
|
-
}
|
|
14501
|
-
const texts = parsed.slice(1).map((t) => ({ handle: t[0], text: t[1], point: t[2] }));
|
|
14502
|
-
return { total, offset, count: texts.length, hasMore: offset + texts.length < total, texts };
|
|
14503
|
-
} catch {
|
|
14504
|
-
return { total: 0, offset: 0, count: 0, hasMore: false, texts: [] };
|
|
14505
|
-
}
|
|
14958
|
+
if (layer) textFilters.push(`(cons 8 "${escapeLispStr(layer)}")`);
|
|
14959
|
+
const filterExpr = `(list '(-4 . "<OR") ${textFilters.join(" ")} '(-4 . "OR>"))`;
|
|
14960
|
+
return streamEntities({
|
|
14961
|
+
filterExpr,
|
|
14962
|
+
extractFields: ["(list (cdr (assoc 5 elist)) (cdr (assoc 1 elist)) (cdr (assoc 10 elist)))"],
|
|
14963
|
+
itemMapper: (item) => ({ handle: item[0], text: item[1], point: item[2] }),
|
|
14964
|
+
offset,
|
|
14965
|
+
limit,
|
|
14966
|
+
hasFilter: !!layer,
|
|
14967
|
+
warnThreshold: UNFILTERED_WARN_THRESHOLD,
|
|
14968
|
+
overLimitMsg: "\u8BF7\u4F7F\u7528 layer \u8FC7\u6EE4",
|
|
14969
|
+
resultProp: "texts"
|
|
14970
|
+
});
|
|
14506
14971
|
}
|
|
14507
14972
|
async function streamBlockRefs({ blockName = null, offset = 0, limit = 100 }) {
|
|
14508
14973
|
const filters = [`(cons 0 "INSERT")`];
|
|
14509
|
-
if (blockName) filters.push(`(cons 2 "${blockName}")`);
|
|
14510
|
-
const
|
|
14511
|
-
|
|
14512
|
-
|
|
14513
|
-
(
|
|
14514
|
-
|
|
14515
|
-
|
|
14516
|
-
|
|
14517
|
-
|
|
14518
|
-
|
|
14519
|
-
|
|
14520
|
-
|
|
14521
|
-
|
|
14522
|
-
(setq e (ssname ss i))
|
|
14523
|
-
(setq elist (entget e))
|
|
14524
|
-
(setq result (cons (list (cdr (assoc 2 elist)) (cdr (assoc 5 elist)) (cdr (assoc 10 elist))) result))
|
|
14525
|
-
(setq i (1+ i))
|
|
14526
|
-
(setq count (1+ count)))
|
|
14527
|
-
(reverse result)))))`;
|
|
14528
|
-
const raw = await cad.sendCommandWithResult(lisp);
|
|
14529
|
-
try {
|
|
14530
|
-
const parsed = JSON.parse(raw);
|
|
14531
|
-
const total = parsed[0] || 0;
|
|
14532
|
-
if (total === -1) {
|
|
14533
|
-
return {
|
|
14534
|
-
total: parsed[1] || 0,
|
|
14535
|
-
offset: 0,
|
|
14536
|
-
count: 0,
|
|
14537
|
-
hasMore: false,
|
|
14538
|
-
refs: [],
|
|
14539
|
-
error: `\u5757\u53C2\u7167\u6570\u91CF (${parsed[1]}) \u8D85\u8FC7\u6700\u5927\u9650\u5236 (${MAX_ENTITY_LIMIT})\uFF0C\u8BF7\u4F7F\u7528 blockName \u8FC7\u6EE4`
|
|
14540
|
-
};
|
|
14541
|
-
}
|
|
14542
|
-
const refs = parsed.slice(1).map((r) => ({ blockName: r[0], handle: r[1], insertionPoint: r[2] }));
|
|
14543
|
-
return { total, offset, count: refs.length, hasMore: offset + refs.length < total, refs };
|
|
14544
|
-
} catch {
|
|
14545
|
-
return { total: 0, offset: 0, count: 0, hasMore: false, refs: [] };
|
|
14546
|
-
}
|
|
14974
|
+
if (blockName) filters.push(`(cons 2 "${escapeLispStr(blockName)}")`);
|
|
14975
|
+
const filterExpr = filters.length > 0 ? `(list ${filters.join(" ")})` : null;
|
|
14976
|
+
return streamEntities({
|
|
14977
|
+
filterExpr,
|
|
14978
|
+
extractFields: ["(list (cdr (assoc 2 elist)) (cdr (assoc 5 elist)) (cdr (assoc 10 elist)))"],
|
|
14979
|
+
itemMapper: (item) => ({ blockName: item[0], handle: item[1], insertionPoint: item[2] }),
|
|
14980
|
+
offset,
|
|
14981
|
+
limit,
|
|
14982
|
+
hasFilter: !!blockName,
|
|
14983
|
+
warnThreshold: UNFILTERED_WARN_THRESHOLD,
|
|
14984
|
+
overLimitMsg: "\u8BF7\u4F7F\u7528 blockName \u8FC7\u6EE4",
|
|
14985
|
+
resultProp: "refs"
|
|
14986
|
+
});
|
|
14547
14987
|
}
|
|
14548
14988
|
var STREAM_CHUNK_SIZE, MAX_ENTITY_LIMIT, UNFILTERED_WARN_THRESHOLD;
|
|
14549
14989
|
var init_streaming = __esm({
|
|
@@ -14555,6 +14995,74 @@ var init_streaming = __esm({
|
|
|
14555
14995
|
}
|
|
14556
14996
|
});
|
|
14557
14997
|
|
|
14998
|
+
// src/cad-rot-helper.js
|
|
14999
|
+
import edge from "edge-js";
|
|
15000
|
+
import path14 from "path";
|
|
15001
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
15002
|
+
function getRotHelper() {
|
|
15003
|
+
if (_rotHelper) return _rotHelper;
|
|
15004
|
+
const dllPath = path14.join(projectRoot, "dist", "cad-rothelper.dll");
|
|
15005
|
+
try {
|
|
15006
|
+
_rotHelper = edge.func({
|
|
15007
|
+
assemblyFile: dllPath,
|
|
15008
|
+
typeName: "CadRotHelper.RotEnumerator",
|
|
15009
|
+
methodName: "EnumerateAll"
|
|
15010
|
+
});
|
|
15011
|
+
return _rotHelper;
|
|
15012
|
+
} catch (e) {
|
|
15013
|
+
error(`ROT \u5E2E\u52A9\u5668\u52A0\u8F7D\u5931\u8D25: ${e.message}`);
|
|
15014
|
+
return null;
|
|
15015
|
+
}
|
|
15016
|
+
}
|
|
15017
|
+
async function discoverCadInstances() {
|
|
15018
|
+
const helper = getRotHelper();
|
|
15019
|
+
if (!helper) {
|
|
15020
|
+
log("ROT \u5E2E\u52A9\u5668\u4E0D\u53EF\u7528\uFF0C\u8DF3\u8FC7 CAD \u5B9E\u4F8B\u53D1\u73B0");
|
|
15021
|
+
return [];
|
|
15022
|
+
}
|
|
15023
|
+
return new Promise((resolve) => {
|
|
15024
|
+
helper(null, (err, result) => {
|
|
15025
|
+
if (err) {
|
|
15026
|
+
error(`ROT \u679A\u4E3E\u5931\u8D25: ${err.message}`);
|
|
15027
|
+
resolve([]);
|
|
15028
|
+
return;
|
|
15029
|
+
}
|
|
15030
|
+
if (!Array.isArray(result)) {
|
|
15031
|
+
resolve([]);
|
|
15032
|
+
return;
|
|
15033
|
+
}
|
|
15034
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15035
|
+
const instances = [];
|
|
15036
|
+
for (const entry of result) {
|
|
15037
|
+
if (!entry.appName) continue;
|
|
15038
|
+
const pidKey = `${entry.appName}-${entry.pid}`;
|
|
15039
|
+
if (seen.has(pidKey)) continue;
|
|
15040
|
+
seen.add(pidKey);
|
|
15041
|
+
const key = `${entry.appName.toLowerCase()}-${entry.pid}`;
|
|
15042
|
+
instances.push({
|
|
15043
|
+
key,
|
|
15044
|
+
platform: entry.appName,
|
|
15045
|
+
pid: entry.pid,
|
|
15046
|
+
hwnd: entry.hwnd,
|
|
15047
|
+
version: entry.version,
|
|
15048
|
+
moniker: entry.name
|
|
15049
|
+
});
|
|
15050
|
+
}
|
|
15051
|
+
log(`ROT \u53D1\u73B0: ${instances.length} \u4E2A CAD \u5B9E\u4F8B (${instances.map((i) => `${i.platform}#${i.pid}`).join(", ")})`);
|
|
15052
|
+
resolve(instances);
|
|
15053
|
+
});
|
|
15054
|
+
});
|
|
15055
|
+
}
|
|
15056
|
+
var __filename, projectRoot, _rotHelper;
|
|
15057
|
+
var init_cad_rot_helper = __esm({
|
|
15058
|
+
"src/cad-rot-helper.js"() {
|
|
15059
|
+
init_logger();
|
|
15060
|
+
__filename = fileURLToPath6(import.meta.url);
|
|
15061
|
+
projectRoot = path14.dirname(path14.dirname(__filename));
|
|
15062
|
+
_rotHelper = null;
|
|
15063
|
+
}
|
|
15064
|
+
});
|
|
15065
|
+
|
|
14558
15066
|
// src/cad-pool.js
|
|
14559
15067
|
var POOL_STRATEGIES, CadConnectionPool, pool;
|
|
14560
15068
|
var init_cad_pool = __esm({
|
|
@@ -14562,6 +15070,8 @@ var init_cad_pool = __esm({
|
|
|
14562
15070
|
init_cad();
|
|
14563
15071
|
init_logger();
|
|
14564
15072
|
init_config();
|
|
15073
|
+
init_cad_rot_helper();
|
|
15074
|
+
init_resource_cache();
|
|
14565
15075
|
POOL_STRATEGIES = {
|
|
14566
15076
|
ROUND_ROBIN: "round-robin",
|
|
14567
15077
|
LEAST_BUSY: "least-busy",
|
|
@@ -14570,9 +15080,8 @@ var init_cad_pool = __esm({
|
|
|
14570
15080
|
CadConnectionPool = class {
|
|
14571
15081
|
_instances = /* @__PURE__ */ new Map();
|
|
14572
15082
|
_maxPoolSize = 3;
|
|
14573
|
-
_activeKey =
|
|
15083
|
+
_activeKey = null;
|
|
14574
15084
|
_strategy = POOL_STRATEGIES.MANUAL;
|
|
14575
|
-
_rrIndex = 0;
|
|
14576
15085
|
_reconnectTimers = /* @__PURE__ */ new Map();
|
|
14577
15086
|
_reconnectCounts = /* @__PURE__ */ new Map();
|
|
14578
15087
|
_maxReconnectAttempts = 10;
|
|
@@ -14582,30 +15091,8 @@ var init_cad_pool = __esm({
|
|
|
14582
15091
|
this._maxPoolSize = config_default.maxPoolSize || 3;
|
|
14583
15092
|
}
|
|
14584
15093
|
getConnection(key) {
|
|
14585
|
-
this._ensureDefault();
|
|
14586
15094
|
return this._instances.get(key)?.connection || null;
|
|
14587
15095
|
}
|
|
14588
|
-
/**
|
|
14589
|
-
* Ensure the default entry exists. Created lazily to avoid
|
|
14590
|
-
* calling getActiveConnection() at module import time (which
|
|
14591
|
-
* breaks tests that mock cad.js).
|
|
14592
|
-
*/
|
|
14593
|
-
_ensureDefault() {
|
|
14594
|
-
if (!this._instances.has("default")) {
|
|
14595
|
-
const defaultConn = getActiveConnection();
|
|
14596
|
-
this._instances.set("default", {
|
|
14597
|
-
key: "default",
|
|
14598
|
-
connection: defaultConn,
|
|
14599
|
-
platform: null,
|
|
14600
|
-
version: null,
|
|
14601
|
-
connected: false,
|
|
14602
|
-
lastPing: Date.now(),
|
|
14603
|
-
createdAt: Date.now(),
|
|
14604
|
-
label: "\u9ED8\u8BA4 CAD",
|
|
14605
|
-
autoReconnect: true
|
|
14606
|
-
});
|
|
14607
|
-
}
|
|
14608
|
-
}
|
|
14609
15096
|
/**
|
|
14610
15097
|
* Connect to a CAD instance and add it to the pool.
|
|
14611
15098
|
* @param {string} key - Instance identifier
|
|
@@ -14613,14 +15100,30 @@ var init_cad_pool = __esm({
|
|
|
14613
15100
|
* @param {object} [options] - Additional options
|
|
14614
15101
|
* @param {string} [options.label] - Human-readable label
|
|
14615
15102
|
* @param {boolean} [options.autoReconnect=true] - Auto-reconnect on failure
|
|
15103
|
+
* @param {number} [options.pid] - Target process PID (find via ROT)
|
|
14616
15104
|
* @param {boolean} [options.makeActive=true] - Set as active after connecting
|
|
14617
15105
|
*/
|
|
14618
15106
|
async connect(key = "default", platform = null, options = {}) {
|
|
14619
|
-
|
|
14620
|
-
const { label, autoReconnect = true, makeActive = true } = options || {};
|
|
15107
|
+
const { label, autoReconnect = true, makeActive = true, pid } = options || {};
|
|
14621
15108
|
if (this._instances.size >= this._maxPoolSize && !this._instances.has(key)) {
|
|
14622
15109
|
throw new Error(`\u8FDE\u63A5\u6C60\u5DF2\u6EE1 (${this._maxPoolSize})\uFF0C\u65E0\u6CD5\u6DFB\u52A0\u65B0\u5B9E\u4F8B "${key}"`);
|
|
14623
15110
|
}
|
|
15111
|
+
if (pid != null) {
|
|
15112
|
+
const instances = await discoverCadInstances();
|
|
15113
|
+
const match = instances.find((i) => i.pid === pid);
|
|
15114
|
+
if (!match) {
|
|
15115
|
+
error(`\u8FDE\u63A5\u6C60: \u672A\u627E\u5230 PID ${pid} \u7684 CAD \u5B9E\u4F8B`);
|
|
15116
|
+
return false;
|
|
15117
|
+
}
|
|
15118
|
+
platform = platform || match.platform;
|
|
15119
|
+
if (key === "default" || key === pid.toString()) {
|
|
15120
|
+
key = match.key;
|
|
15121
|
+
}
|
|
15122
|
+
if (match.moniker) {
|
|
15123
|
+
if (!options) options = {};
|
|
15124
|
+
options._moniker = match.moniker;
|
|
15125
|
+
}
|
|
15126
|
+
}
|
|
14624
15127
|
let entry = this._instances.get(key);
|
|
14625
15128
|
if (entry && entry.connected) {
|
|
14626
15129
|
return true;
|
|
@@ -14642,7 +15145,9 @@ var init_cad_pool = __esm({
|
|
|
14642
15145
|
}
|
|
14643
15146
|
const conn = entry.connection;
|
|
14644
15147
|
try {
|
|
14645
|
-
const
|
|
15148
|
+
const moniker = options._moniker || entry.moniker;
|
|
15149
|
+
const connectOpts = moniker ? { moniker, key } : {};
|
|
15150
|
+
const ok = await conn.connect(platform, connectOpts);
|
|
14646
15151
|
if (ok) {
|
|
14647
15152
|
entry.connected = true;
|
|
14648
15153
|
entry.platform = conn.getPlatform();
|
|
@@ -14666,17 +15171,6 @@ var init_cad_pool = __esm({
|
|
|
14666
15171
|
* Disconnect and remove an instance from the pool.
|
|
14667
15172
|
*/
|
|
14668
15173
|
async disconnect(key) {
|
|
14669
|
-
this._ensureDefault();
|
|
14670
|
-
if (key === "default") {
|
|
14671
|
-
const entry2 = this._instances.get("default");
|
|
14672
|
-
if (entry2) {
|
|
14673
|
-
await entry2.connection.disconnect();
|
|
14674
|
-
entry2.connected = false;
|
|
14675
|
-
entry2.platform = null;
|
|
14676
|
-
entry2.version = null;
|
|
14677
|
-
}
|
|
14678
|
-
return true;
|
|
14679
|
-
}
|
|
14680
15174
|
const entry = this._instances.get(key);
|
|
14681
15175
|
if (!entry) return false;
|
|
14682
15176
|
this._clearReconnectTimer(key);
|
|
@@ -14687,7 +15181,12 @@ var init_cad_pool = __esm({
|
|
|
14687
15181
|
}
|
|
14688
15182
|
this._instances.delete(key);
|
|
14689
15183
|
if (this._activeKey === key) {
|
|
14690
|
-
this.
|
|
15184
|
+
const remaining = Array.from(this._instances.keys());
|
|
15185
|
+
if (remaining.length > 0) {
|
|
15186
|
+
this.setActive(remaining[0]);
|
|
15187
|
+
} else {
|
|
15188
|
+
this._activeKey = null;
|
|
15189
|
+
}
|
|
14691
15190
|
}
|
|
14692
15191
|
log(`\u8FDE\u63A5\u6C60: \u5B9E\u4F8B "${key}" \u5DF2\u65AD\u5F00\u5E76\u79FB\u9664`);
|
|
14693
15192
|
return true;
|
|
@@ -14696,7 +15195,6 @@ var init_cad_pool = __esm({
|
|
|
14696
15195
|
* Set the active instance. All cad.* calls will be routed here.
|
|
14697
15196
|
*/
|
|
14698
15197
|
setActive(key) {
|
|
14699
|
-
this._ensureDefault();
|
|
14700
15198
|
const entry = this._instances.get(key);
|
|
14701
15199
|
if (!entry) {
|
|
14702
15200
|
error(`\u8FDE\u63A5\u6C60: \u5B9E\u4F8B "${key}" \u4E0D\u5B58\u5728`);
|
|
@@ -14704,47 +15202,88 @@ var init_cad_pool = __esm({
|
|
|
14704
15202
|
}
|
|
14705
15203
|
this._activeKey = key;
|
|
14706
15204
|
setActiveConnection(entry.connection);
|
|
15205
|
+
setInstanceKey(key);
|
|
14707
15206
|
cad.connected = entry.connected;
|
|
14708
15207
|
log(`\u8FDE\u63A5\u6C60: \u5DF2\u5207\u6362\u5230\u5B9E\u4F8B "${key}"`);
|
|
15208
|
+
if (this._onInstanceSwitch) {
|
|
15209
|
+
try {
|
|
15210
|
+
this._onInstanceSwitch(key, entry);
|
|
15211
|
+
} catch (e) {
|
|
15212
|
+
error(`\u5207\u6362\u56DE\u8C03\u7528\u9519\u8BEF: ${e.message}`);
|
|
15213
|
+
}
|
|
15214
|
+
}
|
|
14709
15215
|
return true;
|
|
14710
15216
|
}
|
|
15217
|
+
/**
|
|
15218
|
+
* Register a callback invoked after every instance switch.
|
|
15219
|
+
* @param {function} fn - (key, entry) => void
|
|
15220
|
+
*/
|
|
15221
|
+
onInstanceSwitch(fn) {
|
|
15222
|
+
this._onInstanceSwitch = fn;
|
|
15223
|
+
}
|
|
14711
15224
|
/**
|
|
14712
15225
|
* Discover and add all running CAD instances.
|
|
14713
|
-
*
|
|
15226
|
+
* Uses ROT enumeration to find all instances (including multiple of the same platform).
|
|
15227
|
+
* Falls back to GetActiveObject per platform when ROT is unavailable.
|
|
14714
15228
|
*/
|
|
14715
15229
|
async discover() {
|
|
14716
|
-
|
|
14717
|
-
const
|
|
14718
|
-
|
|
14719
|
-
for (const
|
|
14720
|
-
const key =
|
|
15230
|
+
const resultEntries = [];
|
|
15231
|
+
const rotInstances = await discoverCadInstances();
|
|
15232
|
+
const rotHadResults = rotInstances.length > 0;
|
|
15233
|
+
for (const inst of rotInstances) {
|
|
15234
|
+
const key = inst.key;
|
|
14721
15235
|
if (this._instances.has(key) && this._instances.get(key).connected) {
|
|
14722
|
-
|
|
15236
|
+
resultEntries.push(this._instances.get(key));
|
|
14723
15237
|
continue;
|
|
14724
15238
|
}
|
|
14725
|
-
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14730
|
-
|
|
14731
|
-
|
|
14732
|
-
|
|
14733
|
-
|
|
14734
|
-
|
|
14735
|
-
|
|
14736
|
-
|
|
14737
|
-
|
|
14738
|
-
|
|
14739
|
-
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
|
|
15239
|
+
this._instances.set(key, {
|
|
15240
|
+
key,
|
|
15241
|
+
connection: null,
|
|
15242
|
+
platform: inst.platform,
|
|
15243
|
+
pid: inst.pid,
|
|
15244
|
+
version: inst.version,
|
|
15245
|
+
moniker: inst.moniker,
|
|
15246
|
+
connected: false,
|
|
15247
|
+
lastPing: Date.now(),
|
|
15248
|
+
createdAt: Date.now(),
|
|
15249
|
+
label: `${inst.platform} #${inst.pid} ${inst.version || ""}`.trim(),
|
|
15250
|
+
autoReconnect: false
|
|
15251
|
+
});
|
|
15252
|
+
log(`\u8FDE\u63A5\u6C60: \u53D1\u73B0 ${inst.platform} \u5B9E\u4F8B PID=${inst.pid}`);
|
|
15253
|
+
resultEntries.push(this._instances.get(key));
|
|
15254
|
+
}
|
|
15255
|
+
if (!rotHadResults) {
|
|
15256
|
+
const connectWithTimeout = (conn, platform, ms = 4e3) => Promise.race([
|
|
15257
|
+
conn.connect(platform),
|
|
15258
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), ms))
|
|
15259
|
+
]);
|
|
15260
|
+
for (const platform of ["AutoCAD", "ZWCAD", "GStarCAD", "BricsCAD"]) {
|
|
15261
|
+
const key = platform.toLowerCase();
|
|
15262
|
+
if (this._instances.has(key) && this._instances.get(key).connected) continue;
|
|
15263
|
+
try {
|
|
15264
|
+
const tempConn = createCadConnection();
|
|
15265
|
+
const ok = await connectWithTimeout(tempConn, platform);
|
|
15266
|
+
if (ok) {
|
|
15267
|
+
const label = `${platform} ${tempConn.getVersion() || ""}`.trim();
|
|
15268
|
+
this._instances.set(key, {
|
|
15269
|
+
key,
|
|
15270
|
+
connection: tempConn,
|
|
15271
|
+
platform: tempConn.getPlatform(),
|
|
15272
|
+
version: tempConn.getVersion(),
|
|
15273
|
+
connected: true,
|
|
15274
|
+
lastPing: Date.now(),
|
|
15275
|
+
createdAt: Date.now(),
|
|
15276
|
+
label,
|
|
15277
|
+
autoReconnect: true
|
|
15278
|
+
});
|
|
15279
|
+
log(`\u8FDE\u63A5\u6C60: \u53D1\u73B0 ${label}`);
|
|
15280
|
+
resultEntries.push(this._instances.get(key));
|
|
15281
|
+
}
|
|
15282
|
+
} catch (e) {
|
|
14743
15283
|
}
|
|
14744
|
-
} catch (e) {
|
|
14745
15284
|
}
|
|
14746
15285
|
}
|
|
14747
|
-
return
|
|
15286
|
+
return resultEntries.map((e) => ({
|
|
14748
15287
|
key: e.key,
|
|
14749
15288
|
connected: e.connected,
|
|
14750
15289
|
platform: e.platform,
|
|
@@ -14757,7 +15296,6 @@ var init_cad_pool = __esm({
|
|
|
14757
15296
|
* Health check for all instances.
|
|
14758
15297
|
*/
|
|
14759
15298
|
async healthCheck() {
|
|
14760
|
-
this._ensureDefault();
|
|
14761
15299
|
const results = [];
|
|
14762
15300
|
for (const [key, entry] of this._instances) {
|
|
14763
15301
|
try {
|
|
@@ -14803,14 +15341,21 @@ var init_cad_pool = __esm({
|
|
|
14803
15341
|
* Get the active instance.
|
|
14804
15342
|
*/
|
|
14805
15343
|
getActive() {
|
|
14806
|
-
this._ensureDefault();
|
|
14807
15344
|
return this._instances.get(this._activeKey) || null;
|
|
14808
15345
|
}
|
|
14809
15346
|
/**
|
|
14810
15347
|
* Get stats for all instances.
|
|
14811
15348
|
*/
|
|
14812
15349
|
getStats() {
|
|
14813
|
-
this.
|
|
15350
|
+
if (this._instances.size === 0) {
|
|
15351
|
+
return {
|
|
15352
|
+
total: 0,
|
|
15353
|
+
maxPoolSize: this._maxPoolSize,
|
|
15354
|
+
active: null,
|
|
15355
|
+
strategy: this._strategy,
|
|
15356
|
+
instances: []
|
|
15357
|
+
};
|
|
15358
|
+
}
|
|
14814
15359
|
return {
|
|
14815
15360
|
total: this._instances.size,
|
|
14816
15361
|
maxPoolSize: this._maxPoolSize,
|
|
@@ -14822,7 +15367,7 @@ var init_cad_pool = __esm({
|
|
|
14822
15367
|
platform: i.platform,
|
|
14823
15368
|
version: i.version,
|
|
14824
15369
|
label: i.label,
|
|
14825
|
-
queueSize: i.connection
|
|
15370
|
+
queueSize: i.connection?._getQueueSize ? i.connection._getQueueSize() : 0,
|
|
14826
15371
|
lastPingAgo: Date.now() - (i.lastPing || 0),
|
|
14827
15372
|
uptime: i.connected ? Math.round((Date.now() - i.createdAt) / 1e3) : 0
|
|
14828
15373
|
}))
|
|
@@ -14832,7 +15377,7 @@ var init_cad_pool = __esm({
|
|
|
14832
15377
|
* List all instances.
|
|
14833
15378
|
*/
|
|
14834
15379
|
listInstances() {
|
|
14835
|
-
this.
|
|
15380
|
+
if (this._instances.size === 0) return [];
|
|
14836
15381
|
return Array.from(this._instances.values()).map((i) => ({
|
|
14837
15382
|
key: i.key,
|
|
14838
15383
|
connected: i.connected,
|
|
@@ -14844,7 +15389,7 @@ var init_cad_pool = __esm({
|
|
|
14844
15389
|
}));
|
|
14845
15390
|
}
|
|
14846
15391
|
/**
|
|
14847
|
-
* Disconnect all instances.
|
|
15392
|
+
* Disconnect all instances in parallel.
|
|
14848
15393
|
*/
|
|
14849
15394
|
async disconnectAll() {
|
|
14850
15395
|
this.stopHealthCheck();
|
|
@@ -14853,27 +15398,16 @@ var init_cad_pool = __esm({
|
|
|
14853
15398
|
}
|
|
14854
15399
|
this._reconnectTimers.clear();
|
|
14855
15400
|
this._reconnectCounts.clear();
|
|
14856
|
-
|
|
15401
|
+
const entries = Array.from(this._instances.entries());
|
|
15402
|
+
this._instances.clear();
|
|
15403
|
+
this._activeKey = null;
|
|
15404
|
+
await Promise.allSettled(entries.map(async ([key, entry]) => {
|
|
14857
15405
|
try {
|
|
14858
15406
|
await entry.connection.disconnect();
|
|
14859
15407
|
} catch (e) {
|
|
14860
15408
|
error(`\u8FDE\u63A5\u6C60: \u65AD\u5F00 "${key}" \u51FA\u9519: ${e.message}`);
|
|
14861
15409
|
}
|
|
14862
|
-
}
|
|
14863
|
-
this._instances.clear();
|
|
14864
|
-
this._activeKey = "default";
|
|
14865
|
-
const defaultConn = getActiveConnection();
|
|
14866
|
-
this._instances.set("default", {
|
|
14867
|
-
key: "default",
|
|
14868
|
-
connection: defaultConn,
|
|
14869
|
-
platform: null,
|
|
14870
|
-
version: null,
|
|
14871
|
-
connected: false,
|
|
14872
|
-
lastPing: Date.now(),
|
|
14873
|
-
createdAt: Date.now(),
|
|
14874
|
-
label: "\u9ED8\u8BA4 CAD",
|
|
14875
|
-
autoReconnect: true
|
|
14876
|
-
});
|
|
15410
|
+
}));
|
|
14877
15411
|
log("\u8FDE\u63A5\u6C60: \u6240\u6709\u5B9E\u4F8B\u5DF2\u65AD\u5F00");
|
|
14878
15412
|
}
|
|
14879
15413
|
// --- Internal ---
|
|
@@ -14933,7 +15467,7 @@ var init_cad_pool = __esm({
|
|
|
14933
15467
|
});
|
|
14934
15468
|
|
|
14935
15469
|
// src/trigger-engine.js
|
|
14936
|
-
function
|
|
15470
|
+
function escapeLispStr2(v) {
|
|
14937
15471
|
if (typeof v !== "string") return v;
|
|
14938
15472
|
return v.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
14939
15473
|
}
|
|
@@ -14941,10 +15475,10 @@ function buildFilterExpr(filter) {
|
|
|
14941
15475
|
if (!filter || typeof filter !== "object") return "nil";
|
|
14942
15476
|
const parts = [];
|
|
14943
15477
|
if (filter.type) {
|
|
14944
|
-
parts.push(`(cons 0 "${
|
|
15478
|
+
parts.push(`(cons 0 "${escapeLispStr2(filter.type)}")`);
|
|
14945
15479
|
}
|
|
14946
15480
|
if (filter.layer) {
|
|
14947
|
-
parts.push(`(cons 8 "${
|
|
15481
|
+
parts.push(`(cons 8 "${escapeLispStr2(filter.layer)}")`);
|
|
14948
15482
|
}
|
|
14949
15483
|
if (parts.length === 0) return "nil";
|
|
14950
15484
|
return `(list ${parts.join(" ")})`;
|
|
@@ -14993,7 +15527,7 @@ async function evaluateWatch(watch) {
|
|
|
14993
15527
|
return { matched, data: { count } };
|
|
14994
15528
|
}
|
|
14995
15529
|
case "layer_exists": {
|
|
14996
|
-
const lName =
|
|
15530
|
+
const lName = escapeLispStr2(watch.layerName || "");
|
|
14997
15531
|
result = await cad.sendCommandWithResult(
|
|
14998
15532
|
`(progn (if (tblsearch "LAYER" "${lName}") (list 1) (list 0)))`
|
|
14999
15533
|
);
|
|
@@ -15001,7 +15535,7 @@ async function evaluateWatch(watch) {
|
|
|
15001
15535
|
return { matched: exists, data: { exists, layerName: watch.layerName } };
|
|
15002
15536
|
}
|
|
15003
15537
|
case "doc_name": {
|
|
15004
|
-
const pattern =
|
|
15538
|
+
const pattern = escapeLispStr2(watch.pattern || "*");
|
|
15005
15539
|
result = await cad.sendCommandWithResult(
|
|
15006
15540
|
`(progn (setq _dn (getvar "dwgname")) (setq _dm (if (wcmatch _dn "${pattern}") 1 0)) (list _dm _dn))`
|
|
15007
15541
|
);
|
|
@@ -15011,14 +15545,14 @@ async function evaluateWatch(watch) {
|
|
|
15011
15545
|
return { matched, data: { matched: Boolean(matched), name } };
|
|
15012
15546
|
}
|
|
15013
15547
|
case "doc_path": {
|
|
15014
|
-
const pattern =
|
|
15548
|
+
const pattern = escapeLispStr2(watch.pattern || "*");
|
|
15015
15549
|
result = await cad.sendCommandWithResult(
|
|
15016
15550
|
`(progn (setq _dp (getvar "dwgprefix")) (setq _dm (if (wcmatch _dp "${pattern}") 1 0)) (list _dm _dp))`
|
|
15017
15551
|
);
|
|
15018
15552
|
const arr = parseLispList2(result) || [];
|
|
15019
15553
|
const matched = Number(arr[0]) !== 0;
|
|
15020
|
-
const
|
|
15021
|
-
return { matched, data: { matched: Boolean(matched), path:
|
|
15554
|
+
const path21 = String(arr[1] || "");
|
|
15555
|
+
return { matched, data: { matched: Boolean(matched), path: path21 } };
|
|
15022
15556
|
}
|
|
15023
15557
|
case "entity_selected": {
|
|
15024
15558
|
result = await cad.sendCommandWithResult(
|
|
@@ -15188,53 +15722,6 @@ function stripStringsAndComments(code) {
|
|
|
15188
15722
|
const withoutStrings = code.replace(/"([^"\\]*(?:\\.[^"\\]*)*)"/g, "");
|
|
15189
15723
|
return withoutStrings.replace(/;.*$/gm, "");
|
|
15190
15724
|
}
|
|
15191
|
-
var THREAT_BLOCK, THREAT_WARN, THREAT_ALLOW, CVT, SECURITY_RULES, _cachedLevel;
|
|
15192
|
-
var init_lisp_security = __esm({
|
|
15193
|
-
"src/lisp-security.js"() {
|
|
15194
|
-
init_logger();
|
|
15195
|
-
init_config();
|
|
15196
|
-
THREAT_BLOCK = "block";
|
|
15197
|
-
THREAT_WARN = "warn";
|
|
15198
|
-
THREAT_ALLOW = "allow";
|
|
15199
|
-
CVT = {
|
|
15200
|
-
strict: THREAT_BLOCK,
|
|
15201
|
-
standard: THREAT_WARN,
|
|
15202
|
-
relaxed: THREAT_ALLOW
|
|
15203
|
-
};
|
|
15204
|
-
SECURITY_RULES = [
|
|
15205
|
-
{ re: /\bstartapp\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 startapp \u51FD\u6570" },
|
|
15206
|
-
{ re: /\bvl-bt\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 vl-bt \u51FD\u6570" },
|
|
15207
|
-
{ re: /\bvlax-import-type-library\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u5BFC\u5165\u7C7B\u578B\u5E93" },
|
|
15208
|
-
{ re: /\bdos_command_string\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 dos_command_string" },
|
|
15209
|
-
{ re: /\beval\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 eval \u51FD\u6570" },
|
|
15210
|
-
{ re: /\bcommand\s*["\s]*[_(]?\s*["']?\.?\s*_?(?:shell|quit|exit|close|open|new|recover|audit|purge|wblock|export)/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528\u5371\u9669 CAD \u547D\u4EE4" },
|
|
15211
|
-
{ re: /\bload\s*[(\s"]/i, baseSeverity: THREAT_BLOCK, msg: "load \u51FD\u6570\u53EF\u80FD\u52A0\u8F7D\u5916\u90E8\u4EE3\u7801" },
|
|
15212
|
-
{ re: /\b(?:read-line|read-char|write-line|write-char)\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u6587\u4EF6 I/O \u64CD\u4F5C\u53EF\u80FD\u5F71\u54CD\u7CFB\u7EDF" },
|
|
15213
|
-
{ re: /\bvl-file-copy\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6587\u4EF6\u590D\u5236" },
|
|
15214
|
-
{ re: /\bvl-file-delete\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6587\u4EF6\u5220\u9664" },
|
|
15215
|
-
{ re: /\bvl-file-rename\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6587\u4EF6\u91CD\u547D\u540D" },
|
|
15216
|
-
{ re: /\bvl-registry-write[\s\)]/i, baseSeverity: THREAT_BLOCK, msg: "vl-registry-write \u4F1A\u4FEE\u6539\u6CE8\u518C\u8868" },
|
|
15217
|
-
{ re: /\bvl-exit-with-value\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 vl-exit-with-value" },
|
|
15218
|
-
{ re: /\bvl-exit-with-error\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 vl-exit-with-error" },
|
|
15219
|
-
{ re: /\bvlax-add-cmd\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6CE8\u518C\u65B0\u547D\u4EE4" },
|
|
15220
|
-
{ re: /\bvla-Delete\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u76F4\u63A5\u5220\u9664 vla \u5BF9\u8C61" },
|
|
15221
|
-
{ re: /\bvla-Save\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u76F4\u63A5\u4FDD\u5B58\u6587\u6863" },
|
|
15222
|
-
{ re: /\bdirectory\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 directory \u51FD\u6570" },
|
|
15223
|
-
{ re: /\bvla-deletefile\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u5220\u9664\u6587\u4EF6" },
|
|
15224
|
-
{ re: /\bvla-copyfile\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u590D\u5236\u6587\u4EF6" },
|
|
15225
|
-
{ re: /\bvla-movefile\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u79FB\u52A8\u6587\u4EF6" }
|
|
15226
|
-
];
|
|
15227
|
-
_cachedLevel = null;
|
|
15228
|
-
try {
|
|
15229
|
-
onConfigChange(() => {
|
|
15230
|
-
_cachedLevel = null;
|
|
15231
|
-
});
|
|
15232
|
-
} catch (_) {
|
|
15233
|
-
}
|
|
15234
|
-
}
|
|
15235
|
-
});
|
|
15236
|
-
|
|
15237
|
-
// src/lisp-sandbox.js
|
|
15238
15725
|
function getSessionAllowlist(sessionId) {
|
|
15239
15726
|
if (!sessionAllowlist.has(sessionId)) {
|
|
15240
15727
|
sessionAllowlist.set(sessionId, /* @__PURE__ */ new Set());
|
|
@@ -15278,12 +15765,49 @@ function validateLispCode(code, sessionId = null) {
|
|
|
15278
15765
|
summary: blocked ? `\u5B89\u5168\u9650\u5236: ${results.filter((r) => r.blocked).map((r) => r.message).join("; ")}` : "\u901A\u8FC7"
|
|
15279
15766
|
};
|
|
15280
15767
|
}
|
|
15281
|
-
var RULES2, sessionAllowlist;
|
|
15282
|
-
var
|
|
15283
|
-
"src/lisp-
|
|
15768
|
+
var THREAT_BLOCK, THREAT_WARN, THREAT_ALLOW, CVT, SECURITY_RULES, _cachedLevel, RULES2, sessionAllowlist;
|
|
15769
|
+
var init_lisp_security = __esm({
|
|
15770
|
+
"src/lisp-security.js"() {
|
|
15284
15771
|
init_logger();
|
|
15285
15772
|
init_config();
|
|
15286
|
-
|
|
15773
|
+
THREAT_BLOCK = "block";
|
|
15774
|
+
THREAT_WARN = "warn";
|
|
15775
|
+
THREAT_ALLOW = "allow";
|
|
15776
|
+
CVT = {
|
|
15777
|
+
strict: THREAT_BLOCK,
|
|
15778
|
+
standard: THREAT_WARN,
|
|
15779
|
+
relaxed: THREAT_ALLOW
|
|
15780
|
+
};
|
|
15781
|
+
SECURITY_RULES = [
|
|
15782
|
+
{ re: /\bstartapp\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 startapp \u51FD\u6570" },
|
|
15783
|
+
{ re: /\bvl-bt\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 vl-bt \u51FD\u6570" },
|
|
15784
|
+
{ re: /\bvlax-import-type-library\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u5BFC\u5165\u7C7B\u578B\u5E93" },
|
|
15785
|
+
{ re: /\bdos_command_string\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 dos_command_string" },
|
|
15786
|
+
{ re: /\beval\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 eval \u51FD\u6570" },
|
|
15787
|
+
{ re: /\bcommand\s*["\s]*[_(]?\s*["']?\.?\s*_?(?:shell|quit|exit|close|open|new|recover|audit|purge|wblock|export)/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528\u5371\u9669 CAD \u547D\u4EE4" },
|
|
15788
|
+
{ re: /\bload\s*[(\s"]/i, baseSeverity: THREAT_BLOCK, msg: "load \u51FD\u6570\u53EF\u80FD\u52A0\u8F7D\u5916\u90E8\u4EE3\u7801" },
|
|
15789
|
+
{ re: /\b(?:read-line|read-char|write-line|write-char)\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u6587\u4EF6 I/O \u64CD\u4F5C\u53EF\u80FD\u5F71\u54CD\u7CFB\u7EDF" },
|
|
15790
|
+
{ re: /\bvl-file-copy\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6587\u4EF6\u590D\u5236" },
|
|
15791
|
+
{ re: /\bvl-file-delete\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6587\u4EF6\u5220\u9664" },
|
|
15792
|
+
{ re: /\bvl-file-rename\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6587\u4EF6\u91CD\u547D\u540D" },
|
|
15793
|
+
{ re: /\bvl-registry-write[\s\)]/i, baseSeverity: THREAT_BLOCK, msg: "vl-registry-write \u4F1A\u4FEE\u6539\u6CE8\u518C\u8868" },
|
|
15794
|
+
{ re: /\bvl-exit-with-value\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 vl-exit-with-value" },
|
|
15795
|
+
{ re: /\bvl-exit-with-error\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 vl-exit-with-error" },
|
|
15796
|
+
{ re: /\bvlax-add-cmd\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6CE8\u518C\u65B0\u547D\u4EE4" },
|
|
15797
|
+
{ re: /\bvla-Delete\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u76F4\u63A5\u5220\u9664 vla \u5BF9\u8C61" },
|
|
15798
|
+
{ re: /\bvla-Save\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u76F4\u63A5\u4FDD\u5B58\u6587\u6863" },
|
|
15799
|
+
{ re: /\bdirectory\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 directory \u51FD\u6570" },
|
|
15800
|
+
{ re: /\bvla-deletefile\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u5220\u9664\u6587\u4EF6" },
|
|
15801
|
+
{ re: /\bvla-copyfile\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u590D\u5236\u6587\u4EF6" },
|
|
15802
|
+
{ re: /\bvla-movefile\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u79FB\u52A8\u6587\u4EF6" }
|
|
15803
|
+
];
|
|
15804
|
+
_cachedLevel = null;
|
|
15805
|
+
try {
|
|
15806
|
+
onConfigChange(() => {
|
|
15807
|
+
_cachedLevel = null;
|
|
15808
|
+
});
|
|
15809
|
+
} catch (_) {
|
|
15810
|
+
}
|
|
15287
15811
|
RULES2 = SECURITY_RULES;
|
|
15288
15812
|
sessionAllowlist = /* @__PURE__ */ new Map();
|
|
15289
15813
|
}
|
|
@@ -15404,13 +15928,13 @@ ${analysis.errors.map((e) => ` L${e.line}: [${e.rule}] ${e.message}`).join("\n"
|
|
|
15404
15928
|
});
|
|
15405
15929
|
|
|
15406
15930
|
// src/webhook-engine.js
|
|
15407
|
-
import
|
|
15408
|
-
import
|
|
15409
|
-
import
|
|
15931
|
+
import fs10 from "fs";
|
|
15932
|
+
import path15 from "path";
|
|
15933
|
+
import os8 from "os";
|
|
15410
15934
|
function loadWebhooks() {
|
|
15411
15935
|
try {
|
|
15412
|
-
if (
|
|
15413
|
-
webhooks = JSON.parse(
|
|
15936
|
+
if (fs10.existsSync(WEBHOOKS_FILE)) {
|
|
15937
|
+
webhooks = JSON.parse(fs10.readFileSync(WEBHOOKS_FILE, "utf-8"));
|
|
15414
15938
|
}
|
|
15415
15939
|
} catch (e) {
|
|
15416
15940
|
error(`Webhook load error: ${e.message}`);
|
|
@@ -15418,8 +15942,8 @@ function loadWebhooks() {
|
|
|
15418
15942
|
}
|
|
15419
15943
|
function saveWebhooks() {
|
|
15420
15944
|
try {
|
|
15421
|
-
ensureDir(
|
|
15422
|
-
|
|
15945
|
+
ensureDir(path15.dirname(WEBHOOKS_FILE));
|
|
15946
|
+
fs10.writeFileSync(WEBHOOKS_FILE, JSON.stringify(webhooks, null, 2), "utf-8");
|
|
15423
15947
|
} catch (e) {
|
|
15424
15948
|
error(`Webhook save error: ${e.message}`);
|
|
15425
15949
|
}
|
|
@@ -15476,10 +16000,10 @@ function listWebhooks() {
|
|
|
15476
16000
|
}
|
|
15477
16001
|
function getWebhookLog(id) {
|
|
15478
16002
|
const sanitized = String(id).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
15479
|
-
const logPath =
|
|
16003
|
+
const logPath = path15.join(os8.homedir(), ".atlisp", `webhook-${sanitized}.log`);
|
|
15480
16004
|
try {
|
|
15481
|
-
if (!
|
|
15482
|
-
return
|
|
16005
|
+
if (!fs10.existsSync(logPath)) return [];
|
|
16006
|
+
return fs10.readFileSync(logPath, "utf-8").split("\n").filter(Boolean).map((l) => JSON.parse(l));
|
|
15483
16007
|
} catch (e) {
|
|
15484
16008
|
error(`Webhook log read error [${sanitized}]: ${e.message}`);
|
|
15485
16009
|
return [];
|
|
@@ -15490,30 +16014,30 @@ var init_webhook_engine = __esm({
|
|
|
15490
16014
|
"src/webhook-engine.js"() {
|
|
15491
16015
|
init_logger();
|
|
15492
16016
|
init_handler_utils();
|
|
15493
|
-
WEBHOOKS_FILE =
|
|
16017
|
+
WEBHOOKS_FILE = path15.join(os8.homedir(), ".atlisp", "webhooks.json");
|
|
15494
16018
|
webhooks = [];
|
|
15495
16019
|
loadWebhooks();
|
|
15496
16020
|
}
|
|
15497
16021
|
});
|
|
15498
16022
|
|
|
15499
16023
|
// src/audit-log.js
|
|
15500
|
-
import
|
|
15501
|
-
import
|
|
15502
|
-
import
|
|
16024
|
+
import fs11 from "fs";
|
|
16025
|
+
import path16 from "path";
|
|
16026
|
+
import os9 from "os";
|
|
15503
16027
|
import zlib from "zlib";
|
|
15504
16028
|
function rotateIfNeeded() {
|
|
15505
16029
|
try {
|
|
15506
|
-
if (
|
|
16030
|
+
if (fs11.existsSync(AUDIT_FILE) && fs11.statSync(AUDIT_FILE).size > MAX_LOG_SIZE2) {
|
|
15507
16031
|
const rotated = AUDIT_FILE.replace(".log", `.${Date.now()}.log`);
|
|
15508
|
-
|
|
16032
|
+
fs11.renameSync(AUDIT_FILE, rotated);
|
|
15509
16033
|
try {
|
|
15510
|
-
const compressed = zlib.gzipSync(
|
|
15511
|
-
|
|
15512
|
-
|
|
16034
|
+
const compressed = zlib.gzipSync(fs11.readFileSync(rotated));
|
|
16035
|
+
fs11.writeFileSync(rotated + ".gz", compressed);
|
|
16036
|
+
fs11.unlinkSync(rotated);
|
|
15513
16037
|
} catch (e) {
|
|
15514
16038
|
error(`Audit log compression failed, keeping raw file: ${e.message}`);
|
|
15515
16039
|
try {
|
|
15516
|
-
|
|
16040
|
+
fs11.unlinkSync(rotated + ".gz");
|
|
15517
16041
|
} catch {
|
|
15518
16042
|
}
|
|
15519
16043
|
}
|
|
@@ -15537,15 +16061,15 @@ function writeAuditEntry(entry) {
|
|
|
15537
16061
|
user: entry.user || "",
|
|
15538
16062
|
role: entry.role || ""
|
|
15539
16063
|
}) + "\n";
|
|
15540
|
-
|
|
16064
|
+
fs11.appendFileSync(AUDIT_FILE, line, "utf-8");
|
|
15541
16065
|
} catch (e) {
|
|
15542
16066
|
error(`Audit log write error: ${e.message}`);
|
|
15543
16067
|
}
|
|
15544
16068
|
}
|
|
15545
16069
|
function queryAuditLog(filters = {}) {
|
|
15546
16070
|
try {
|
|
15547
|
-
if (!
|
|
15548
|
-
const content =
|
|
16071
|
+
if (!fs11.existsSync(AUDIT_FILE)) return { total: 0, offset: 0, count: 0, entries: [] };
|
|
16072
|
+
const content = fs11.readFileSync(AUDIT_FILE, "utf-8");
|
|
15549
16073
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
15550
16074
|
let entries = lines.map((l) => {
|
|
15551
16075
|
try {
|
|
@@ -15577,8 +16101,8 @@ function queryAuditLog(filters = {}) {
|
|
|
15577
16101
|
}
|
|
15578
16102
|
function getAuditStats() {
|
|
15579
16103
|
try {
|
|
15580
|
-
if (!
|
|
15581
|
-
const content =
|
|
16104
|
+
if (!fs11.existsSync(AUDIT_FILE)) return { totalEntries: 0, tools: {}, errors: 0 };
|
|
16105
|
+
const content = fs11.readFileSync(AUDIT_FILE, "utf-8");
|
|
15582
16106
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
15583
16107
|
const toolCounts = {};
|
|
15584
16108
|
let errors = 0;
|
|
@@ -15594,7 +16118,7 @@ function getAuditStats() {
|
|
|
15594
16118
|
totalEntries: lines.length,
|
|
15595
16119
|
tools: toolCounts,
|
|
15596
16120
|
errors,
|
|
15597
|
-
fileSize:
|
|
16121
|
+
fileSize: fs11.existsSync(AUDIT_FILE) ? fs11.statSync(AUDIT_FILE).size : 0,
|
|
15598
16122
|
filePath: AUDIT_FILE
|
|
15599
16123
|
};
|
|
15600
16124
|
} catch (e) {
|
|
@@ -15606,8 +16130,8 @@ var init_audit_log = __esm({
|
|
|
15606
16130
|
"src/audit-log.js"() {
|
|
15607
16131
|
init_logger();
|
|
15608
16132
|
init_handler_utils();
|
|
15609
|
-
AUDIT_DIR =
|
|
15610
|
-
AUDIT_FILE =
|
|
16133
|
+
AUDIT_DIR = path16.join(os9.homedir(), "@lisp", "logs");
|
|
16134
|
+
AUDIT_FILE = path16.join(AUDIT_DIR, "audit.log");
|
|
15611
16135
|
MAX_LOG_SIZE2 = 10 * 1024 * 1024;
|
|
15612
16136
|
MAX_LOG_AGE = 90 * 24 * 60 * 60 * 1e3;
|
|
15613
16137
|
}
|
|
@@ -15641,14 +16165,17 @@ var init_agent_context = __esm({
|
|
|
15641
16165
|
});
|
|
15642
16166
|
|
|
15643
16167
|
// src/tool-validators.js
|
|
15644
|
-
function
|
|
16168
|
+
function validationError(msg) {
|
|
16169
|
+
return new MCPError(ERROR_CODES.INVALID_ARGS, msg);
|
|
16170
|
+
}
|
|
16171
|
+
function validateProps(args, props, required, path21 = "") {
|
|
15645
16172
|
for (const [key, prop] of Object.entries(props)) {
|
|
15646
|
-
const fullKey =
|
|
16173
|
+
const fullKey = path21 ? `${path21}.${key}` : key;
|
|
15647
16174
|
const isOptional = !required.includes(key);
|
|
15648
16175
|
const val = args[key];
|
|
15649
16176
|
if (val === void 0 || val === null) {
|
|
15650
16177
|
if (isOptional) continue;
|
|
15651
|
-
throw
|
|
16178
|
+
throw validationError(`Missing required argument: ${fullKey}`);
|
|
15652
16179
|
}
|
|
15653
16180
|
if (prop.type === "object" && prop.properties && typeof val === "object" && !Array.isArray(val)) {
|
|
15654
16181
|
const subRequired = prop.required || [];
|
|
@@ -15663,46 +16190,46 @@ function validateProps(args, props, required, path20 = "") {
|
|
|
15663
16190
|
const actualType = typeof val;
|
|
15664
16191
|
const expectedType = prop.type || "string";
|
|
15665
16192
|
if (expectedType === "string" && actualType !== "string" && actualType !== "number") {
|
|
15666
|
-
throw
|
|
16193
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected string, got ${actualType}`);
|
|
15667
16194
|
}
|
|
15668
16195
|
if ((expectedType === "object" || expectedType === "array") && (actualType !== "object" || val === null)) {
|
|
15669
|
-
throw
|
|
16196
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected ${expectedType}, got ${actualType}`);
|
|
15670
16197
|
}
|
|
15671
16198
|
if (expectedType === "array" && !Array.isArray(val)) {
|
|
15672
|
-
throw
|
|
16199
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected array, got ${actualType}`);
|
|
15673
16200
|
}
|
|
15674
16201
|
if (expectedType === "object" && Array.isArray(val)) {
|
|
15675
|
-
throw
|
|
16202
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected object, got array`);
|
|
15676
16203
|
}
|
|
15677
16204
|
if ((expectedType === "number" || expectedType === "integer") && actualType !== "number") {
|
|
15678
16205
|
if (expectedType === "integer" && !Number.isInteger(val)) {
|
|
15679
|
-
throw
|
|
16206
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected integer, got ${actualType}`);
|
|
15680
16207
|
}
|
|
15681
16208
|
if (expectedType === "number") {
|
|
15682
|
-
throw
|
|
16209
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected number, got ${actualType}`);
|
|
15683
16210
|
}
|
|
15684
16211
|
}
|
|
15685
16212
|
if (expectedType === "boolean" && actualType !== "boolean") {
|
|
15686
|
-
throw
|
|
16213
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected boolean, got ${actualType}`);
|
|
15687
16214
|
}
|
|
15688
16215
|
if (prop.enum && !prop.enum.includes(val)) {
|
|
15689
|
-
throw
|
|
16216
|
+
throw validationError(`Invalid value for argument ${fullKey}: must be one of ${prop.enum.join(", ")}`);
|
|
15690
16217
|
}
|
|
15691
16218
|
if (expectedType === "string" && typeof prop.maxLength === "number" && String(val).length > prop.maxLength) {
|
|
15692
|
-
throw
|
|
16219
|
+
throw validationError(`Argument ${fullKey} exceeds max length of ${prop.maxLength}`);
|
|
15693
16220
|
}
|
|
15694
16221
|
if ((expectedType === "number" || expectedType === "integer") && prop.minimum != null && val < prop.minimum) {
|
|
15695
|
-
throw
|
|
16222
|
+
throw validationError(`Argument ${fullKey} must be >= ${prop.minimum}`);
|
|
15696
16223
|
}
|
|
15697
16224
|
if ((expectedType === "number" || expectedType === "integer") && prop.maximum != null && val > prop.maximum) {
|
|
15698
|
-
throw
|
|
16225
|
+
throw validationError(`Argument ${fullKey} must be <= ${prop.maximum}`);
|
|
15699
16226
|
}
|
|
15700
16227
|
}
|
|
15701
16228
|
}
|
|
15702
16229
|
function validateToolArgs(name, args) {
|
|
15703
16230
|
const toolDef = toolsByName.get(name);
|
|
15704
16231
|
if (!toolDef) {
|
|
15705
|
-
throw
|
|
16232
|
+
throw validationError(`Unknown tool: ${name}`);
|
|
15706
16233
|
}
|
|
15707
16234
|
const schema = toolDef.inputSchema;
|
|
15708
16235
|
if (!schema || !schema.properties) return true;
|
|
@@ -15710,7 +16237,7 @@ function validateToolArgs(name, args) {
|
|
|
15710
16237
|
const required = schema.required || [];
|
|
15711
16238
|
for (const req of required) {
|
|
15712
16239
|
if (!(req in (args || {}))) {
|
|
15713
|
-
throw
|
|
16240
|
+
throw validationError(`Missing required argument: ${req}`);
|
|
15714
16241
|
}
|
|
15715
16242
|
}
|
|
15716
16243
|
validateProps(args || {}, props, required);
|
|
@@ -15719,6 +16246,7 @@ function validateToolArgs(name, args) {
|
|
|
15719
16246
|
var init_tool_validators = __esm({
|
|
15720
16247
|
"src/tool-validators.js"() {
|
|
15721
16248
|
init_tools();
|
|
16249
|
+
init_errors();
|
|
15722
16250
|
}
|
|
15723
16251
|
});
|
|
15724
16252
|
|
|
@@ -15829,7 +16357,7 @@ function registerTool(toolDef, handler) {
|
|
|
15829
16357
|
}
|
|
15830
16358
|
customTools.push(toolDef);
|
|
15831
16359
|
customHandlers.set(toolDef.name, handler);
|
|
15832
|
-
|
|
16360
|
+
tools43.push(toolDef);
|
|
15833
16361
|
return true;
|
|
15834
16362
|
}
|
|
15835
16363
|
function callCustomTool(name, args) {
|
|
@@ -15849,73 +16377,92 @@ var init_tool_registry = __esm({
|
|
|
15849
16377
|
});
|
|
15850
16378
|
|
|
15851
16379
|
// src/tool-executor.js
|
|
16380
|
+
function resolveConn(instance) {
|
|
16381
|
+
if (instance) return pool.getConnection(instance) || resolveCadConnection();
|
|
16382
|
+
return cad;
|
|
16383
|
+
}
|
|
16384
|
+
async function writeAuditSuccess(name, args, options) {
|
|
16385
|
+
writeAuditEntry({
|
|
16386
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16387
|
+
tool: name,
|
|
16388
|
+
args: args || {},
|
|
16389
|
+
sessionId: options.sessionId || "",
|
|
16390
|
+
result: "success"
|
|
16391
|
+
});
|
|
16392
|
+
}
|
|
16393
|
+
async function writeAuditError(name, args, options, error2) {
|
|
16394
|
+
writeAuditEntry({
|
|
16395
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16396
|
+
tool: name,
|
|
16397
|
+
args: args || {},
|
|
16398
|
+
sessionId: options.sessionId || "",
|
|
16399
|
+
result: "error",
|
|
16400
|
+
error: error2.message
|
|
16401
|
+
});
|
|
16402
|
+
}
|
|
16403
|
+
async function beginUndo(instance) {
|
|
16404
|
+
const conn = resolveConn(instance);
|
|
16405
|
+
if (conn?.connected) {
|
|
16406
|
+
try {
|
|
16407
|
+
await conn.sendCommand('(command "_.UNDO" "_BEGIN")');
|
|
16408
|
+
return true;
|
|
16409
|
+
} catch (e) {
|
|
16410
|
+
error(`UNDO_BEGIN failed: ${e.message}`);
|
|
16411
|
+
}
|
|
16412
|
+
}
|
|
16413
|
+
return false;
|
|
16414
|
+
}
|
|
16415
|
+
async function endUndo(instance) {
|
|
16416
|
+
const conn = resolveConn(instance);
|
|
16417
|
+
try {
|
|
16418
|
+
await conn.sendCommand('(command "_.UNDO" "_END")');
|
|
16419
|
+
} catch (_) {
|
|
16420
|
+
}
|
|
16421
|
+
}
|
|
15852
16422
|
async function handleToolCall(name, args, options = {}) {
|
|
15853
16423
|
const handler = TOOL_HANDLERS[name];
|
|
15854
16424
|
if (!handler) {
|
|
15855
16425
|
const customResult = callCustomTool(name, args);
|
|
15856
16426
|
if (customResult !== null) return customResult;
|
|
15857
|
-
return
|
|
16427
|
+
return mcpErrorResponse(new MCPError(ERROR_CODES.HANDLER_NOT_FOUND, `\u672A\u77E5\u5DE5\u5177: ${name}`));
|
|
15858
16428
|
}
|
|
15859
16429
|
const isReadOnly = READ_ONLY_TOOLS.has(name);
|
|
15860
16430
|
const notifyProgress = options.notifyProgress || null;
|
|
15861
16431
|
const rateCheck = checkToolRateLimit(name, isReadOnly, options.sessionId);
|
|
15862
16432
|
if (!rateCheck.allowed) {
|
|
15863
|
-
return
|
|
16433
|
+
return mcpErrorResponse(new MCPError(ERROR_CODES.RATE_LIMITED, `\u5DE5\u5177\u8C03\u7528\u9891\u7387\u8D85\u9650\uFF0C\u8BF7 ${rateCheck.retryAfter} \u79D2\u540E\u91CD\u8BD5`));
|
|
15864
16434
|
}
|
|
15865
16435
|
return progressContext.run({ notifyProgress }, async () => {
|
|
15866
16436
|
setNotifyProgress(notifyProgress);
|
|
16437
|
+
const instance = args?.instance || null;
|
|
15867
16438
|
let undoBegun = false;
|
|
15868
16439
|
try {
|
|
15869
16440
|
validateToolArgs(name, args || {});
|
|
15870
|
-
const instance = args?.instance || null;
|
|
15871
16441
|
if (instance) {
|
|
15872
16442
|
const ctx = mcpContext.getStore();
|
|
15873
16443
|
ctx._toolInstance = instance;
|
|
15874
16444
|
}
|
|
15875
16445
|
if (!isReadOnly) {
|
|
15876
|
-
|
|
15877
|
-
if (targetConn?.connected) {
|
|
15878
|
-
try {
|
|
15879
|
-
await targetConn.sendCommand('(command "_.UNDO" "_BEGIN")');
|
|
15880
|
-
undoBegun = true;
|
|
15881
|
-
} catch (e) {
|
|
15882
|
-
error(`UNDO_BEGIN failed: ${e.message}`);
|
|
15883
|
-
}
|
|
15884
|
-
}
|
|
16446
|
+
undoBegun = await beginUndo(instance);
|
|
15885
16447
|
}
|
|
15886
16448
|
const np = getNotifyProgress();
|
|
15887
16449
|
if (np) np(1, 1, `\u6B63\u5728\u6267\u884C ${name}...`);
|
|
15888
16450
|
const result = await handler(args || {});
|
|
15889
16451
|
if (np) np(1, 1, `${name} \u6267\u884C\u5B8C\u6210`);
|
|
15890
|
-
|
|
15891
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15892
|
-
tool: name,
|
|
15893
|
-
args: args || {},
|
|
15894
|
-
sessionId: options.sessionId || "",
|
|
15895
|
-
result: result?.isError ? "error" : "success"
|
|
15896
|
-
});
|
|
16452
|
+
await writeAuditSuccess(name, args, options);
|
|
15897
16453
|
notifyResourceChanges(name);
|
|
15898
16454
|
return result;
|
|
15899
16455
|
} catch (e) {
|
|
15900
16456
|
error(`Tool call error [${name}]: ${e.message}`, { tool: name, args });
|
|
15901
|
-
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
result: "error",
|
|
15907
|
-
error: e.message
|
|
15908
|
-
});
|
|
15909
|
-
return { content: [{ type: "text", text: `\u5DE5\u5177\u6267\u884C\u9519\u8BEF: ${e.message}` }], isError: true };
|
|
16457
|
+
await writeAuditError(name, args, options, e);
|
|
16458
|
+
if (e.message.startsWith("Missing required") || e.message.startsWith("Invalid type")) {
|
|
16459
|
+
return mcpErrorResponse(new MCPError(ERROR_CODES.INVALID_ARGS, e.message));
|
|
16460
|
+
}
|
|
16461
|
+
return mcpErrorResponse(e);
|
|
15910
16462
|
} finally {
|
|
15911
16463
|
const ctx = mcpContext.getStore();
|
|
15912
16464
|
if (ctx) ctx._toolInstance = null;
|
|
15913
|
-
if (undoBegun)
|
|
15914
|
-
try {
|
|
15915
|
-
await cad.sendCommand('(command "_.UNDO" "_END")');
|
|
15916
|
-
} catch (_) {
|
|
15917
|
-
}
|
|
15918
|
-
}
|
|
16465
|
+
if (undoBegun) await endUndo(instance);
|
|
15919
16466
|
}
|
|
15920
16467
|
});
|
|
15921
16468
|
}
|
|
@@ -15932,14 +16479,12 @@ var init_tool_executor = __esm({
|
|
|
15932
16479
|
init_cad();
|
|
15933
16480
|
init_cad_pool();
|
|
15934
16481
|
init_audit_log();
|
|
16482
|
+
init_errors();
|
|
15935
16483
|
init_tool_registry();
|
|
15936
16484
|
}
|
|
15937
16485
|
});
|
|
15938
16486
|
|
|
15939
16487
|
// src/mcp-tools.js
|
|
15940
|
-
import fs11 from "fs";
|
|
15941
|
-
import path15 from "path";
|
|
15942
|
-
import os9 from "os";
|
|
15943
16488
|
import { formatCode as formatCode2 } from "@atlisp/lint/dist/formatter.js";
|
|
15944
16489
|
import { lintProject as lintProject2 } from "@atlisp/lint/dist/project.js";
|
|
15945
16490
|
import { RULES as RULES3 } from "@atlisp/lint/dist/rules.js";
|
|
@@ -15956,7 +16501,6 @@ var TOOL_HANDLERS;
|
|
|
15956
16501
|
var init_mcp_tools = __esm({
|
|
15957
16502
|
"src/mcp-tools.js"() {
|
|
15958
16503
|
init_handler_loader();
|
|
15959
|
-
init_prompt_handlers();
|
|
15960
16504
|
init_streaming();
|
|
15961
16505
|
init_constants();
|
|
15962
16506
|
init_cad();
|
|
@@ -15964,13 +16508,24 @@ var init_mcp_tools = __esm({
|
|
|
15964
16508
|
init_tools();
|
|
15965
16509
|
init_mcp_server_state();
|
|
15966
16510
|
init_trigger_engine();
|
|
15967
|
-
|
|
16511
|
+
init_lisp_security();
|
|
15968
16512
|
init_lint_analyzer();
|
|
15969
16513
|
init_repl_engine();
|
|
15970
16514
|
init_webhook_engine();
|
|
15971
16515
|
init_audit_log();
|
|
15972
16516
|
init_agent_context();
|
|
16517
|
+
init_resource_handlers();
|
|
16518
|
+
init_subscription_manager();
|
|
16519
|
+
init_skill_handlers();
|
|
16520
|
+
init_meta_handlers();
|
|
15973
16521
|
init_tool_executor();
|
|
16522
|
+
pool.onInstanceSwitch(() => {
|
|
16523
|
+
for (const uri of CAD_RESOURCE_URIS) {
|
|
16524
|
+
if (isSubscribed(uri)) {
|
|
16525
|
+
notify2(uri, null);
|
|
16526
|
+
}
|
|
16527
|
+
}
|
|
16528
|
+
});
|
|
15974
16529
|
TOOL_HANDLERS = {
|
|
15975
16530
|
// === CAD Connection ===
|
|
15976
16531
|
connect_cad: lazy("connect_cad", (a) => a?.platform),
|
|
@@ -16007,14 +16562,8 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16007
16562
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
16008
16563
|
},
|
|
16009
16564
|
// === Prompts ===
|
|
16010
|
-
list_prompts:
|
|
16011
|
-
|
|
16012
|
-
return { content: [{ type: "text", text: JSON.stringify(prompts) }] };
|
|
16013
|
-
},
|
|
16014
|
-
get_prompt: async (a) => {
|
|
16015
|
-
const prompt = await getPrompt2(a.name, a.args || {});
|
|
16016
|
-
return { content: prompt.messages.map((m) => ({ type: "text", text: m.content.text || m.content })) };
|
|
16017
|
-
},
|
|
16565
|
+
list_prompts: list_prompts_handler,
|
|
16566
|
+
get_prompt: get_prompt_handler,
|
|
16018
16567
|
// === Entity Operations ===
|
|
16019
16568
|
get_entity: lazy("get_entity", (a) => a?.handle),
|
|
16020
16569
|
set_entity: lazy("set_entity", (a) => [a?.handle, a?.property, a?.value]),
|
|
@@ -16301,6 +16850,35 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16301
16850
|
draw_ray: lazy("draw_ray", (a) => [a.point, a.direction]),
|
|
16302
16851
|
draw_leader: lazy("draw_leader", (a) => [a.points, a.annotation]),
|
|
16303
16852
|
draw_table: lazy("draw_table", (a) => [a.insertionPoint, a.rows, a.columns, a.rowHeight, a.colWidth]),
|
|
16853
|
+
// === Batch Concurrent ===
|
|
16854
|
+
batch_concurrent_tasks: async (a) => {
|
|
16855
|
+
if (!a.tasks || !Array.isArray(a.tasks) || a.tasks.length === 0) {
|
|
16856
|
+
return { content: [{ type: "text", text: "\u9700\u8981 tasks \u6570\u7EC4" }], isError: true };
|
|
16857
|
+
}
|
|
16858
|
+
if (a.tasks.length > 50) {
|
|
16859
|
+
return { content: [{ type: "text", text: "\u6700\u591A\u652F\u6301 50 \u4E2A\u5E76\u53D1\u4EFB\u52A1" }], isError: true };
|
|
16860
|
+
}
|
|
16861
|
+
const results = await Promise.allSettled(a.tasks.map(async (task, idx) => {
|
|
16862
|
+
const handler = TOOL_HANDLERS[task.tool];
|
|
16863
|
+
if (!handler) return { index: idx, tool: task.tool, instance: task.instance, ok: false, error: `\u672A\u77E5\u5DE5\u5177: ${task.tool}` };
|
|
16864
|
+
const ctx = mcpContext.getStore();
|
|
16865
|
+
const prevInstance = ctx?._toolInstance || null;
|
|
16866
|
+
if (ctx && task.instance) ctx._toolInstance = task.instance;
|
|
16867
|
+
try {
|
|
16868
|
+
const result = await handler(task.args || {});
|
|
16869
|
+
return { index: idx, tool: task.tool, instance: task.instance, ok: !result.isError, data: result.content?.[0]?.text || result };
|
|
16870
|
+
} catch (e) {
|
|
16871
|
+
return { index: idx, tool: task.tool, instance: task.instance, ok: false, error: e.message };
|
|
16872
|
+
} finally {
|
|
16873
|
+
if (ctx) ctx._toolInstance = prevInstance;
|
|
16874
|
+
}
|
|
16875
|
+
}));
|
|
16876
|
+
const output = results.map((r, idx) => {
|
|
16877
|
+
if (r.status === "fulfilled") return r.value;
|
|
16878
|
+
return { index: idx, tool: a.tasks[idx].tool, instance: a.tasks[idx].instance, ok: false, error: r.reason?.message || "Unknown error" };
|
|
16879
|
+
});
|
|
16880
|
+
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
16881
|
+
},
|
|
16304
16882
|
// === Batch Transaction ===
|
|
16305
16883
|
batch_transaction: lazy("batch_transaction"),
|
|
16306
16884
|
// === Watch / Trigger ===
|
|
@@ -16457,6 +17035,14 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16457
17035
|
},
|
|
16458
17036
|
cad_pool_switch: (a) => {
|
|
16459
17037
|
const ok = pool.setActive(a.key);
|
|
17038
|
+
if (ok) {
|
|
17039
|
+
clearCache();
|
|
17040
|
+
for (const uri of CAD_RESOURCE_URIS) {
|
|
17041
|
+
if (isSubscribed(uri)) {
|
|
17042
|
+
notify2(uri, null);
|
|
17043
|
+
}
|
|
17044
|
+
}
|
|
17045
|
+
}
|
|
16460
17046
|
return { content: [{ type: "text", text: ok ? `\u5DF2\u5207\u6362\u5230\u5B9E\u4F8B ${a.key}` : `\u5B9E\u4F8B ${a.key} \u4E0D\u5B58\u5728` }] };
|
|
16461
17047
|
},
|
|
16462
17048
|
cad_pool_health: async () => {
|
|
@@ -16468,8 +17054,9 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16468
17054
|
return { content: [{ type: "text", text: JSON.stringify(stats, null, 2) }] };
|
|
16469
17055
|
},
|
|
16470
17056
|
cad_pool_connect: async (a) => {
|
|
16471
|
-
const ok = await pool.connect(a.key, a.platform, { label: a.label, makeActive: a.makeActive !== false });
|
|
16472
|
-
|
|
17057
|
+
const ok = await pool.connect(a.key, a.platform, { label: a.label, pid: a.pid, makeActive: a.makeActive !== false });
|
|
17058
|
+
const label = a.key || (a.pid != null ? `PID ${a.pid}` : "default");
|
|
17059
|
+
return { content: [{ type: "text", text: ok ? `\u5B9E\u4F8B "${label}" \u5DF2\u8FDE\u63A5` : `\u5B9E\u4F8B "${label}" \u8FDE\u63A5\u5931\u8D25` }] };
|
|
16473
17060
|
},
|
|
16474
17061
|
cad_pool_disconnect: async (a) => {
|
|
16475
17062
|
const ok = await pool.disconnect(a.key);
|
|
@@ -16519,261 +17106,15 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16519
17106
|
return { content: [{ type: "text", text: "\u4E0A\u4E0B\u6587\u5DF2\u6E05\u9664" }] };
|
|
16520
17107
|
},
|
|
16521
17108
|
// === Meta Tools ===
|
|
16522
|
-
search_tools
|
|
16523
|
-
|
|
16524
|
-
|
|
16525
|
-
const text = results.length ? `\u627E\u5230 ${results.length} \u4E2A\u5DE5\u5177:
|
|
16526
|
-
${results.map((t) => `${t.name}: ${t.description}`).join("\n")}` : `\u672A\u627E\u5230\u5305\u542B "${a.query}" \u7684\u5DE5\u5177`;
|
|
16527
|
-
return { content: [{ type: "text", text }] };
|
|
16528
|
-
},
|
|
16529
|
-
list_tools_by_category: async (a) => {
|
|
16530
|
-
const categories = {};
|
|
16531
|
-
for (const t of tools42) {
|
|
16532
|
-
let cat = "\u5176\u4ED6";
|
|
16533
|
-
const n = t.name;
|
|
16534
|
-
if (/^(draw_|create_3d_|create_box|create_cone|create_cylinder|create_sphere|create_torus|create_wedge|extrude_|revolve_|boolean_|slice_solid|thicken_|offset_surface|create_loft_|create_region)/.test(n)) cat = "\u7ED8\u56FE\u4E0E3D";
|
|
16535
|
-
else if (/^(move_|copy_|rotate_|scale_|mirror_|offset_|array_|batch_)/.test(n)) cat = "\u4FEE\u6539";
|
|
16536
|
-
else if (/^(trim_|extend_|fillet|chamfer|break_|join_|stretch)/.test(n)) cat = "\u7F16\u8F91";
|
|
16537
|
-
else if (/^(create_layer|delete_layer|set_layer|layer_)/.test(n)) cat = "\u56FE\u5C42";
|
|
16538
|
-
else if (/^(create_block|insert_block|explode_block|get_block|set_block|batch_get_block|batch_set_block)/.test(n)) cat = "\u5757";
|
|
16539
|
-
else if (/^(create_dim|list_dim|set_dim|create_hatch|set_hatch)/.test(n)) cat = "\u6807\u6CE8\u4E0E\u586B\u5145";
|
|
16540
|
-
else if (/^(create_ucs|set_ucs|delete_ucs|list_ucs|get_current_ucs|create_layout|delete_layout|rename_layout|set_layout|list_layouts|get_current_layout)/.test(n)) cat = "\u5750\u6807\u7CFB\u4E0E\u5E03\u5C40";
|
|
16541
|
-
else if (/^(create_viewport|set_viewport|lock_viewport|unlock_viewport|maximize_viewport)/.test(n)) cat = "\u89C6\u53E3";
|
|
16542
|
-
else if (/^find_/.test(n)) cat = "\u7A7A\u95F4\u67E5\u8BE2";
|
|
16543
|
-
else if (/^(select_|get_entity|set_entity|delete_entity|get_bounding_box)/.test(n)) cat = "\u9009\u62E9\u4E0E\u5C5E\u6027";
|
|
16544
|
-
else if (/^(open_dwg|save_dwg|export_|import_|close_dwg|publish_)/.test(n)) cat = "\u6587\u4EF6";
|
|
16545
|
-
else if (/^(plot_|save_pdf|batch_plot|publish_layouts)/.test(n)) cat = "\u6253\u5370";
|
|
16546
|
-
else if (/^(get_xdata|set_xdata|delete_xdata|list_xdata|copxy_xdata|search_by_xdata|export_xdata|import_xdata)/.test(n)) cat = "\u6269\u5C55\u6570\u636E";
|
|
16547
|
-
else if (/^(create_sheet|open_sheet|list_sheet|add_sheet|delete_sheet|publish_sheet|sheet_|reorder_sheet|create_subset|list_subset|set_sheet)/.test(n)) cat = "\u56FE\u7EB8\u96C6";
|
|
16548
|
-
else if (/^(attach_|detach_|reload_|list_attached|get_pdf|create_dgn|create_dwf|import_dxf|import_dgn|export_dgn|create_hyper|remove_hyper|xref|bind_xref|clip_xref|path_xref)/.test(n)) cat = "\u53C2\u7167\u4E0E\u5E95\u56FE";
|
|
16549
|
-
else if (/^(create_text|create_mleader|create_linetype|list_text|list_linetype|list_mleader|load_linetype|create_dimension_style|set_dimstyle|list_dimension_styles|set_mleader_style)/.test(n)) cat = "\u6837\u5F0F";
|
|
16550
|
-
else if (/^(purge_|drawing_audit|drawing_recover|overkill)/.test(n)) cat = "\u6E05\u7406";
|
|
16551
|
-
else if (/^(find_text|replace_text|set_text_|justify_|convert_text|explode_text)/.test(n)) cat = "\u6587\u5B57";
|
|
16552
|
-
else if (/^(eval_lisp|connect_cad|get_cad|get_platform|get_system|at_command|new_document|bring_to_front|install_atlisp|init_atlisp|get_system_status)/.test(n)) cat = "\u7CFB\u7EDF";
|
|
16553
|
-
else if (/^(list_packages|search_packages|install_package|get_function_usage|list_symbols|import_funlib)/.test(n)) cat = "\u5305\u4E0E\u51FD\u6570";
|
|
16554
|
-
else if (/^(pipeline_|watch_|lisp_repl|webhook_|sandbox_|audit_|cad_pool_|external_|list_data|export_to|import_external)/.test(n)) cat = "\u9AD8\u7EA7";
|
|
16555
|
-
else if (/^(list_prompts|get_prompt|search_tools|list_tools_by_category)/.test(n)) cat = "\u5143\u5DE5\u5177";
|
|
16556
|
-
else if (/^(agent_)/.test(n)) cat = "Agent\u4E0A\u4E0B\u6587";
|
|
16557
|
-
if (!categories[cat]) categories[cat] = [];
|
|
16558
|
-
categories[cat].push(t.name);
|
|
16559
|
-
}
|
|
16560
|
-
if (a.category) {
|
|
16561
|
-
const names = categories[a.category];
|
|
16562
|
-
return { content: [{ type: "text", text: names ? `${a.category} (${names.length}):
|
|
16563
|
-
${names.join("\n")}` : `\u672A\u627E\u5230\u5206\u7C7B: ${a.category}` }] };
|
|
16564
|
-
}
|
|
16565
|
-
const lines = [];
|
|
16566
|
-
for (const [cat, names] of Object.entries(categories)) {
|
|
16567
|
-
lines.push(`## ${cat} (${names.length})`);
|
|
16568
|
-
}
|
|
16569
|
-
lines.push(`
|
|
16570
|
-
\u5171 ${Object.keys(categories).length} \u4E2A\u5206\u7C7B`);
|
|
16571
|
-
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
16572
|
-
},
|
|
17109
|
+
search_tools,
|
|
17110
|
+
list_tools_by_category,
|
|
17111
|
+
get_tool_info,
|
|
16573
17112
|
// === Skill Management ===
|
|
16574
|
-
skill_search
|
|
16575
|
-
|
|
16576
|
-
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
if (fs11.existsSync(cachePath)) cache = JSON.parse(fs11.readFileSync(cachePath, "utf-8"));
|
|
16580
|
-
} catch {
|
|
16581
|
-
}
|
|
16582
|
-
let index = cache && Date.now() - cache.fetchedAt < 36e5 ? cache : null;
|
|
16583
|
-
if (!index) {
|
|
16584
|
-
try {
|
|
16585
|
-
const resp = await fetch(registryUrl, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
16586
|
-
if (resp.ok) {
|
|
16587
|
-
index = await resp.json();
|
|
16588
|
-
index.fetchedAt = Date.now();
|
|
16589
|
-
try {
|
|
16590
|
-
fs11.writeFileSync(cachePath, JSON.stringify(index, null, 2), "utf-8");
|
|
16591
|
-
} catch {
|
|
16592
|
-
}
|
|
16593
|
-
}
|
|
16594
|
-
} catch {
|
|
16595
|
-
}
|
|
16596
|
-
}
|
|
16597
|
-
if (!index || !index.skills) return { content: [{ type: "text", text: "\u65E0\u6CD5\u83B7\u53D6 skill \u6CE8\u518C\u8868\u7D22\u5F15" }], isError: true };
|
|
16598
|
-
const q = (a.query || "").toLowerCase();
|
|
16599
|
-
const results = index.skills.filter(
|
|
16600
|
-
(s) => s.name.toLowerCase().includes(q) || (s.description || "").toLowerCase().includes(q) || (s.tags || []).some((t) => t.toLowerCase().includes(q))
|
|
16601
|
-
);
|
|
16602
|
-
if (!results.length) return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5339\u914D "${a.query}" \u7684 skill` }] };
|
|
16603
|
-
const lines = [`\u627E\u5230 ${results.length} \u4E2A skill:
|
|
16604
|
-
`];
|
|
16605
|
-
for (const s of results) {
|
|
16606
|
-
lines.push(`**${s.name}**`);
|
|
16607
|
-
if (s.description) lines.push(` \u63CF\u8FF0: ${s.description}`);
|
|
16608
|
-
if (s.tags?.length) lines.push(` \u6807\u7B7E: ${s.tags.join(", ")}`);
|
|
16609
|
-
if (s.version) lines.push(` \u7248\u672C: ${s.version}`);
|
|
16610
|
-
lines.push("");
|
|
16611
|
-
}
|
|
16612
|
-
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
16613
|
-
},
|
|
16614
|
-
skill_install: async (a) => {
|
|
16615
|
-
if (!a.name) return { content: [{ type: "text", text: "\u9700\u8981 skill \u540D\u79F0" }], isError: true };
|
|
16616
|
-
const registryUrl = process.env.SKILL_REGISTRY_URL || "https://raw.githubusercontent.com/atlisp/skill-registry/main/index.json";
|
|
16617
|
-
const cachePath = path15.join(os9.homedir(), ".atlisp", "skill-registry-cache.json");
|
|
16618
|
-
let cache = null;
|
|
16619
|
-
try {
|
|
16620
|
-
if (fs11.existsSync(cachePath)) cache = JSON.parse(fs11.readFileSync(cachePath, "utf-8"));
|
|
16621
|
-
} catch {
|
|
16622
|
-
}
|
|
16623
|
-
let index = cache;
|
|
16624
|
-
if (!index || Date.now() - index.fetchedAt > 36e5) {
|
|
16625
|
-
try {
|
|
16626
|
-
const resp = await fetch(registryUrl, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
16627
|
-
if (resp.ok) {
|
|
16628
|
-
index = await resp.json();
|
|
16629
|
-
index.fetchedAt = Date.now();
|
|
16630
|
-
try {
|
|
16631
|
-
fs11.writeFileSync(cachePath, JSON.stringify(index, null, 2), "utf-8");
|
|
16632
|
-
} catch {
|
|
16633
|
-
}
|
|
16634
|
-
}
|
|
16635
|
-
} catch {
|
|
16636
|
-
}
|
|
16637
|
-
}
|
|
16638
|
-
if (!index || !index.skills) return { content: [{ type: "text", text: "\u65E0\u6CD5\u83B7\u53D6 skill \u6CE8\u518C\u8868\u7D22\u5F15" }], isError: true };
|
|
16639
|
-
const skill = index.skills.find((s) => s.name === a.name);
|
|
16640
|
-
if (!skill) return { content: [{ type: "text", text: `\u672A\u627E\u5230 skill: ${a.name}` }], isError: true };
|
|
16641
|
-
const downloadUrl = skill.download_url || skill.url;
|
|
16642
|
-
if (!downloadUrl) return { content: [{ type: "text", text: `Skill "${a.name}" \u6CA1\u6709\u4E0B\u8F7D\u5730\u5740` }], isError: true };
|
|
16643
|
-
let content;
|
|
16644
|
-
try {
|
|
16645
|
-
const resp = await fetch(downloadUrl, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
16646
|
-
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
|
16647
|
-
content = await resp.text();
|
|
16648
|
-
} catch (e) {
|
|
16649
|
-
return { content: [{ type: "text", text: `\u4E0B\u8F7D\u5931\u8D25: ${e.message}` }], isError: true };
|
|
16650
|
-
}
|
|
16651
|
-
const skillsDir = path15.join(os9.homedir(), ".atlisp", "skills");
|
|
16652
|
-
try {
|
|
16653
|
-
fs11.mkdirSync(skillsDir, { recursive: true });
|
|
16654
|
-
} catch {
|
|
16655
|
-
}
|
|
16656
|
-
const safeName = a.name.replace(/[^a-zA-Z0-9\u4e00-\u9fff_-]/g, "-").substring(0, 40);
|
|
16657
|
-
const skillFile = path15.join(skillsDir, `skill-${safeName}.md`);
|
|
16658
|
-
if (fs11.existsSync(skillFile)) {
|
|
16659
|
-
return { content: [{ type: "text", text: `Skill "${a.name}" \u5DF2\u5B89\u88C5 (${skillFile})` }], isError: true };
|
|
16660
|
-
}
|
|
16661
|
-
let finalContent = content;
|
|
16662
|
-
if (!content.match(/^---\n/)) {
|
|
16663
|
-
const tags = (skill.tags || []).join(", ");
|
|
16664
|
-
finalContent = `---
|
|
16665
|
-
name: ${a.name}
|
|
16666
|
-
description: ${skill.description || ""}
|
|
16667
|
-
tags: ${tags}
|
|
16668
|
-
---
|
|
16669
|
-
|
|
16670
|
-
${content}`;
|
|
16671
|
-
}
|
|
16672
|
-
fs11.writeFileSync(skillFile, finalContent, "utf-8");
|
|
16673
|
-
return { content: [{ type: "text", text: `\u2705 ${skill.name} \u5B89\u88C5\u6210\u529F
|
|
16674
|
-
\u6587\u4EF6: ${skillFile}${skill.version ? `
|
|
16675
|
-
\u7248\u672C: ${skill.version}` : ""}` }] };
|
|
16676
|
-
},
|
|
16677
|
-
skill_list_installed: async () => {
|
|
16678
|
-
const skillsDir = path15.join(os9.homedir(), ".atlisp", "skills");
|
|
16679
|
-
if (!fs11.existsSync(skillsDir)) return { content: [{ type: "text", text: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684 skill" }] };
|
|
16680
|
-
const results = [];
|
|
16681
|
-
try {
|
|
16682
|
-
const entries = fs11.readdirSync(skillsDir, { withFileTypes: true });
|
|
16683
|
-
for (const entry of entries) {
|
|
16684
|
-
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
16685
|
-
const fullPath = path15.join(skillsDir, entry.name);
|
|
16686
|
-
try {
|
|
16687
|
-
const raw = fs11.readFileSync(fullPath, "utf-8");
|
|
16688
|
-
const match = raw.match(/^---\n([\s\S]*?)\n---/);
|
|
16689
|
-
if (match) {
|
|
16690
|
-
const fm = {};
|
|
16691
|
-
for (const line of match[1].split("\n")) {
|
|
16692
|
-
const sep = line.indexOf(":");
|
|
16693
|
-
if (sep > 0) fm[line.slice(0, sep).trim()] = line.slice(sep + 1).trim();
|
|
16694
|
-
}
|
|
16695
|
-
results.push({ name: fm.name || entry.name.replace(".md", ""), description: fm.description || "", tags: fm.tags || "" });
|
|
16696
|
-
} else {
|
|
16697
|
-
results.push({ name: entry.name.replace(".md", ""), description: "", tags: "" });
|
|
16698
|
-
}
|
|
16699
|
-
} catch {
|
|
16700
|
-
}
|
|
16701
|
-
}
|
|
16702
|
-
}
|
|
16703
|
-
} catch {
|
|
16704
|
-
}
|
|
16705
|
-
if (!results.length) return { content: [{ type: "text", text: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684 skill" }] };
|
|
16706
|
-
const lines = [`\u5DF2\u5B89\u88C5 ${results.length} \u4E2A skill:
|
|
16707
|
-
`];
|
|
16708
|
-
for (const s of results) {
|
|
16709
|
-
lines.push(`**${s.name}**${s.description ? ` \u2014 ${s.description}` : ""}`);
|
|
16710
|
-
if (s.tags) lines.push(` \u6807\u7B7E: ${s.tags}`);
|
|
16711
|
-
}
|
|
16712
|
-
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
16713
|
-
},
|
|
16714
|
-
skill_uninstall: async (a) => {
|
|
16715
|
-
if (!a.name) return { content: [{ type: "text", text: "\u9700\u8981 skill \u540D\u79F0" }], isError: true };
|
|
16716
|
-
const skillsDir = path15.join(os9.homedir(), ".atlisp", "skills");
|
|
16717
|
-
if (!fs11.existsSync(skillsDir)) return { content: [{ type: "text", text: `\u672A\u5B89\u88C5 skill: ${a.name}` }], isError: true };
|
|
16718
|
-
let found = null;
|
|
16719
|
-
try {
|
|
16720
|
-
const entries = fs11.readdirSync(skillsDir, { withFileTypes: true });
|
|
16721
|
-
for (const entry of entries) {
|
|
16722
|
-
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
16723
|
-
const fullPath = path15.join(skillsDir, entry.name);
|
|
16724
|
-
try {
|
|
16725
|
-
const raw = fs11.readFileSync(fullPath, "utf-8");
|
|
16726
|
-
const match = raw.match(/^---\n([\s\S]*?)\n---/);
|
|
16727
|
-
if (match) {
|
|
16728
|
-
for (const line of match[1].split("\n")) {
|
|
16729
|
-
if (line.startsWith("name:") && line.slice(5).trim() === a.name) {
|
|
16730
|
-
found = fullPath;
|
|
16731
|
-
break;
|
|
16732
|
-
}
|
|
16733
|
-
}
|
|
16734
|
-
} else if (entry.name.replace(".md", "") === a.name) {
|
|
16735
|
-
found = fullPath;
|
|
16736
|
-
}
|
|
16737
|
-
} catch {
|
|
16738
|
-
}
|
|
16739
|
-
if (found) break;
|
|
16740
|
-
}
|
|
16741
|
-
}
|
|
16742
|
-
} catch {
|
|
16743
|
-
}
|
|
16744
|
-
if (!found) return { content: [{ type: "text", text: `\u672A\u5B89\u88C5 skill: ${a.name}` }], isError: true };
|
|
16745
|
-
fs11.unlinkSync(found);
|
|
16746
|
-
return { content: [{ type: "text", text: `\u2705 ${a.name} \u5DF2\u5378\u8F7D` }] };
|
|
16747
|
-
},
|
|
16748
|
-
skill_list_categories: async () => {
|
|
16749
|
-
const registryUrl = process.env.SKILL_REGISTRY_URL || "https://raw.githubusercontent.com/atlisp/skill-registry/main/index.json";
|
|
16750
|
-
const cachePath = path15.join(os9.homedir(), ".atlisp", "skill-registry-cache.json");
|
|
16751
|
-
let cache = null;
|
|
16752
|
-
try {
|
|
16753
|
-
if (fs11.existsSync(cachePath)) cache = JSON.parse(fs11.readFileSync(cachePath, "utf-8"));
|
|
16754
|
-
} catch {
|
|
16755
|
-
}
|
|
16756
|
-
let index = cache && Date.now() - cache.fetchedAt < 36e5 ? cache : null;
|
|
16757
|
-
if (!index) {
|
|
16758
|
-
try {
|
|
16759
|
-
const resp = await fetch(registryUrl, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
16760
|
-
if (resp.ok) {
|
|
16761
|
-
index = await resp.json();
|
|
16762
|
-
try {
|
|
16763
|
-
fs11.writeFileSync(cachePath, JSON.stringify(index, null, 2), "utf-8");
|
|
16764
|
-
} catch {
|
|
16765
|
-
}
|
|
16766
|
-
}
|
|
16767
|
-
} catch {
|
|
16768
|
-
}
|
|
16769
|
-
}
|
|
16770
|
-
if (!index || !index.skills) return { content: [{ type: "text", text: "\u65E0\u6CD5\u83B7\u53D6 skill \u6CE8\u518C\u8868\u7D22\u5F15" }], isError: true };
|
|
16771
|
-
const cats = /* @__PURE__ */ new Set();
|
|
16772
|
-
for (const s of index.skills) for (const t of s.tags || []) cats.add(t);
|
|
16773
|
-
const sorted = Array.from(cats).sort();
|
|
16774
|
-
return { content: [{ type: "text", text: sorted.length ? `\u6CE8\u518C\u8868\u5206\u7C7B (${sorted.length}):
|
|
16775
|
-
${sorted.join("\n")}` : "\u6682\u65E0\u5206\u7C7B" }] };
|
|
16776
|
-
}
|
|
17113
|
+
skill_search,
|
|
17114
|
+
skill_install,
|
|
17115
|
+
skill_list_installed,
|
|
17116
|
+
skill_uninstall,
|
|
17117
|
+
skill_list_categories
|
|
16777
17118
|
};
|
|
16778
17119
|
}
|
|
16779
17120
|
});
|
|
@@ -16864,7 +17205,7 @@ var init_mcp_server_state = __esm({
|
|
|
16864
17205
|
progressContext = new AsyncLocalStorage();
|
|
16865
17206
|
sessionServers = /* @__PURE__ */ new Map();
|
|
16866
17207
|
sessionTransports = /* @__PURE__ */ new Map();
|
|
16867
|
-
mcpHandlers = { tools:
|
|
17208
|
+
mcpHandlers = { tools: tools43, handleToolCall };
|
|
16868
17209
|
_stdioServer = null;
|
|
16869
17210
|
_pendingResourceUpdated = /* @__PURE__ */ new Set();
|
|
16870
17211
|
_resourceUpdatedTimer = null;
|
|
@@ -16888,11 +17229,12 @@ function mcpError(text) {
|
|
|
16888
17229
|
return { content: [{ type: "text", text: String(text) }], isError: true };
|
|
16889
17230
|
}
|
|
16890
17231
|
async function ensureCadConnected() {
|
|
16891
|
-
const { cad: cad2 } = await Promise.resolve().then(() => (init_cad(), cad_exports));
|
|
16892
|
-
|
|
16893
|
-
|
|
17232
|
+
const { cad: cad2, resolveCadConnection: resolveCadConnection2 } = await Promise.resolve().then(() => (init_cad(), cad_exports));
|
|
17233
|
+
const conn = resolveCadConnection2();
|
|
17234
|
+
if (!conn.connected) {
|
|
17235
|
+
await conn.connect();
|
|
16894
17236
|
}
|
|
16895
|
-
if (!
|
|
17237
|
+
if (!conn.connected) {
|
|
16896
17238
|
throw createError(ERROR_CODES.CAD_NOT_CONNECTED);
|
|
16897
17239
|
}
|
|
16898
17240
|
}
|
|
@@ -17077,7 +17419,7 @@ __export(resource_handlers_exports, {
|
|
|
17077
17419
|
readResource: () => readResource
|
|
17078
17420
|
});
|
|
17079
17421
|
import fs13 from "fs";
|
|
17080
|
-
import
|
|
17422
|
+
import path17 from "path";
|
|
17081
17423
|
function propertyPairsToObject(pairs) {
|
|
17082
17424
|
if (!Array.isArray(pairs)) return null;
|
|
17083
17425
|
const obj = {};
|
|
@@ -17849,7 +18191,7 @@ async function getDwgList() {
|
|
|
17849
18191
|
}
|
|
17850
18192
|
}
|
|
17851
18193
|
function loadStandardsFile(filename) {
|
|
17852
|
-
const filePath =
|
|
18194
|
+
const filePath = path17.join(STANDARDS_DIR, filename);
|
|
17853
18195
|
try {
|
|
17854
18196
|
const raw = fs13.readFileSync(filePath, "utf-8");
|
|
17855
18197
|
return JSON.parse(raw);
|
|
@@ -17949,6 +18291,119 @@ async function getDwgContext() {
|
|
|
17949
18291
|
};
|
|
17950
18292
|
}
|
|
17951
18293
|
}
|
|
18294
|
+
async function getDrawingAnalysis(params = {}) {
|
|
18295
|
+
const snapshot = await getCadSnapshot();
|
|
18296
|
+
if (!snapshot || !snapshot.cadConnected) {
|
|
18297
|
+
return { connected: false, error: "CAD \u672A\u8FDE\u63A5" };
|
|
18298
|
+
}
|
|
18299
|
+
try {
|
|
18300
|
+
const detailedCode = `(progn
|
|
18301
|
+
(vl-load-com)
|
|
18302
|
+
(setq r nil)
|
|
18303
|
+
;; entity counts by type
|
|
18304
|
+
(if (setq ss (ssget "_X"))
|
|
18305
|
+
(progn
|
|
18306
|
+
(setq total (sslength ss) i 0 cnt nil)
|
|
18307
|
+
(while (< i total)
|
|
18308
|
+
(setq typ (cdr (assoc 0 (entget (ssname ss i)))))
|
|
18309
|
+
(setq cnt (if (assoc typ cnt) (subst (cons typ (1+ (cdr (assoc typ cnt)))) (assoc typ cnt) cnt) (cons (cons typ 1) cnt)))
|
|
18310
|
+
(setq i (1+ i)))
|
|
18311
|
+
(setq r (cons (cons "entityCount" total) r))
|
|
18312
|
+
(setq r (cons (cons "entityByType" cnt) r)))
|
|
18313
|
+
(setq r (cons (cons "entityCount" 0) r)))
|
|
18314
|
+
;; block usage
|
|
18315
|
+
(setq blocks nil)
|
|
18316
|
+
(vlax-for b (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
|
|
18317
|
+
(if (and (= (vla-get-IsXref b) :vlax-false) (/= (vla-get-Name b) "*Model_Space") (/= (vla-get-Name b) "*Paper_Space"))
|
|
18318
|
+
(setq blocks (cons (list "name" (vla-get-Name b) "count" (vla-get-Count b) "isDynamic" (vla-get-IsDynamicBlock b)) blocks))))
|
|
18319
|
+
(setq r (cons (cons "blockUsage" blocks) r))
|
|
18320
|
+
;; layer summary
|
|
18321
|
+
(setq layers nil le (tblnext "layer" t))
|
|
18322
|
+
(while le
|
|
18323
|
+
(setq ln (cdr (assoc 2 le)) lc (cdr (assoc 62 le)) ll (cdr (assoc 6 le)))
|
|
18324
|
+
(setq layers (cons (list "name" ln "color" (if (< lc 0) (- lc) lc) "off" (< lc 0) "linetype" ll) layers))
|
|
18325
|
+
(setq le (tblnext "layer" nil)))
|
|
18326
|
+
(setq r (cons (cons "layers" layers) r))
|
|
18327
|
+
;; text stats
|
|
18328
|
+
(if (setq ts (ssget "_X" '((0 . "TEXT,MTEXT"))))
|
|
18329
|
+
(progn
|
|
18330
|
+
(setq tc (sslength ts) th nil ti 0)
|
|
18331
|
+
(while (< ti tc)
|
|
18332
|
+
(setq h (cdr (assoc 40 (entget (ssname ts ti)))))
|
|
18333
|
+
(if h (setq th (cons h th)))
|
|
18334
|
+
(setq ti (1+ ti)))
|
|
18335
|
+
(setq th (vl-sort th '<))
|
|
18336
|
+
(setq r (cons (cons "textCount" tc) r))
|
|
18337
|
+
(setq r (cons (cons "textHeights" (list "min" (car th) "max" (last th) "median" (nth (fix (/ (length th) 2)) th))) r)))
|
|
18338
|
+
(setq r (cons (cons "textCount" 0) r)))
|
|
18339
|
+
;; system variables
|
|
18340
|
+
(setq r (cons (cons "sysvars" (list
|
|
18341
|
+
(cons "ltscale" (getvar "ltscale"))
|
|
18342
|
+
(cons "dimscale" (getvar "dimscale"))
|
|
18343
|
+
(cons "insunits" (getvar "insunits"))
|
|
18344
|
+
(cons "measurement" (getvar "measurement"))
|
|
18345
|
+
(cons "celtype" (getvar "celtype"))
|
|
18346
|
+
(cons "clayer" (getvar "clayer"))
|
|
18347
|
+
(cons "cecolor" (getvar "cecolor"))
|
|
18348
|
+
(cons "osmode" (getvar "osmode"))
|
|
18349
|
+
(cons "snapmode" (getvar "snapmode"))
|
|
18350
|
+
(cons "gridmode" (getvar "gridmode"))
|
|
18351
|
+
(cons "orthomode" (getvar "orthomode"))
|
|
18352
|
+
(cons "plinetype" (getvar "plinetype"))
|
|
18353
|
+
(cons "fillmode" (getvar "fillmode"))
|
|
18354
|
+
(cons "pickstyle" (getvar "pickstyle"))
|
|
18355
|
+
)) r))
|
|
18356
|
+
(vl-prin1-to-string (reverse r)))`;
|
|
18357
|
+
const resultStr = await cad.sendCommandWithResult(detailedCode);
|
|
18358
|
+
const parsed = parseLispRecursive(resultStr);
|
|
18359
|
+
if (!parsed || !Array.isArray(parsed)) {
|
|
18360
|
+
return { connected: true, error: "\u5206\u6790\u7ED3\u679C\u89E3\u6790\u5931\u8D25" };
|
|
18361
|
+
}
|
|
18362
|
+
const analysis = {};
|
|
18363
|
+
for (const pair of parsed) {
|
|
18364
|
+
if (Array.isArray(pair) && pair.length >= 2) {
|
|
18365
|
+
analysis[String(pair[0])] = pair[1];
|
|
18366
|
+
}
|
|
18367
|
+
}
|
|
18368
|
+
return { connected: true, ...analysis };
|
|
18369
|
+
} catch (e) {
|
|
18370
|
+
log(`getDrawingAnalysis error: ${e.message}`);
|
|
18371
|
+
return { connected: true, error: e.message };
|
|
18372
|
+
}
|
|
18373
|
+
}
|
|
18374
|
+
function getToolCategories() {
|
|
18375
|
+
const cats = {};
|
|
18376
|
+
for (const t of tools43) {
|
|
18377
|
+
const cat = t.annotations?.category || "\u5176\u4ED6";
|
|
18378
|
+
if (!cats[cat]) cats[cat] = { count: 0, tools: [] };
|
|
18379
|
+
cats[cat].count++;
|
|
18380
|
+
cats[cat].tools.push(t.name);
|
|
18381
|
+
}
|
|
18382
|
+
return Object.entries(cats).map(([category, info]) => ({
|
|
18383
|
+
category,
|
|
18384
|
+
count: info.count,
|
|
18385
|
+
tools: info.tools
|
|
18386
|
+
})).sort((a, b) => b.count - a.count);
|
|
18387
|
+
}
|
|
18388
|
+
async function checkDrawingStandards() {
|
|
18389
|
+
const standards = getDraftingStandards();
|
|
18390
|
+
if (!standards || standards.error) {
|
|
18391
|
+
return { ok: false, error: standards?.error || "\u5236\u56FE\u89C4\u8303\u672A\u52A0\u8F7D" };
|
|
18392
|
+
}
|
|
18393
|
+
try {
|
|
18394
|
+
const issues = [];
|
|
18395
|
+
for (const rule of standards.layers || []) {
|
|
18396
|
+
const code = `(tblsearch "LAYER" "${escapeLispString(rule.name || rule.pattern)}")`;
|
|
18397
|
+
const exists = await cad.sendCommandWithResult(code);
|
|
18398
|
+
if (rule.required && (!exists || exists === "nil" || exists === "")) {
|
|
18399
|
+
issues.push({ type: "missing_layer", message: `\u7F3A\u5C11\u5FC5\u9700\u56FE\u5C42: ${rule.name}` });
|
|
18400
|
+
}
|
|
18401
|
+
}
|
|
18402
|
+
return { ok: issues.length === 0, issues };
|
|
18403
|
+
} catch (e) {
|
|
18404
|
+
return { ok: false, error: e.message };
|
|
18405
|
+
}
|
|
18406
|
+
}
|
|
17952
18407
|
function getToolRelationships() {
|
|
17953
18408
|
return {
|
|
17954
18409
|
selection: {
|
|
@@ -18204,6 +18659,12 @@ async function readResource(uri) {
|
|
|
18204
18659
|
return await getDwgContext();
|
|
18205
18660
|
case "atlisp://tools/relationships":
|
|
18206
18661
|
return getToolRelationships();
|
|
18662
|
+
case "atlisp://dwg/analysis":
|
|
18663
|
+
return await getDrawingAnalysis(params);
|
|
18664
|
+
case "atlisp://tools/categories":
|
|
18665
|
+
return getToolCategories();
|
|
18666
|
+
case "atlisp://dwg/standards/check":
|
|
18667
|
+
return await checkDrawingStandards();
|
|
18207
18668
|
default:
|
|
18208
18669
|
throw new Error(`\u8D44\u6E90\u4E0D\u5B58\u5728: ${uri}`);
|
|
18209
18670
|
}
|
|
@@ -18219,6 +18680,7 @@ var init_resource_handlers = __esm({
|
|
|
18219
18680
|
init_handler_utils();
|
|
18220
18681
|
init_errors();
|
|
18221
18682
|
init_config();
|
|
18683
|
+
init_tools();
|
|
18222
18684
|
ENTITY_PROPERTIES_LISP = `
|
|
18223
18685
|
(defun entity:to-list (val)
|
|
18224
18686
|
(cond
|
|
@@ -18298,11 +18760,11 @@ init_subscription_manager();
|
|
|
18298
18760
|
init_subscription_manager();
|
|
18299
18761
|
init_sse_session();
|
|
18300
18762
|
init_config();
|
|
18301
|
-
import
|
|
18763
|
+
import path20 from "path";
|
|
18302
18764
|
import fs16 from "fs";
|
|
18303
18765
|
import http from "http";
|
|
18304
18766
|
import https from "https";
|
|
18305
|
-
import { fileURLToPath as
|
|
18767
|
+
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
18306
18768
|
import { createRequire as createRequire2 } from "module";
|
|
18307
18769
|
import express2 from "express";
|
|
18308
18770
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -18315,12 +18777,13 @@ init_cad_pool();
|
|
|
18315
18777
|
init_subscription_manager();
|
|
18316
18778
|
init_mcp_server_state();
|
|
18317
18779
|
init_sse_session();
|
|
18780
|
+
import os10 from "os";
|
|
18318
18781
|
import express from "express";
|
|
18319
18782
|
import { randomUUID as randomUUID6, createHash } from "crypto";
|
|
18320
18783
|
import fs14 from "fs";
|
|
18321
|
-
import
|
|
18322
|
-
import { fileURLToPath as
|
|
18323
|
-
import
|
|
18784
|
+
import path18 from "path";
|
|
18785
|
+
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
18786
|
+
import iconv2 from "iconv-lite";
|
|
18324
18787
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
18325
18788
|
|
|
18326
18789
|
// src/cad-event-bus.js
|
|
@@ -18432,7 +18895,6 @@ var TOOL_PERMISSIONS = {
|
|
|
18432
18895
|
"measure_*": "read",
|
|
18433
18896
|
"stream_*": "read",
|
|
18434
18897
|
"watch_list": "read",
|
|
18435
|
-
"pipeline_list": "read",
|
|
18436
18898
|
// Write tools
|
|
18437
18899
|
"create_*": "write",
|
|
18438
18900
|
"set_*": "write",
|
|
@@ -18452,8 +18914,6 @@ var TOOL_PERMISSIONS = {
|
|
|
18452
18914
|
"import_*": "import",
|
|
18453
18915
|
// Admin
|
|
18454
18916
|
"config_*": "admin",
|
|
18455
|
-
"pipeline_save": "admin",
|
|
18456
|
-
"pipeline_delete": "admin",
|
|
18457
18917
|
"webhook_*": "admin",
|
|
18458
18918
|
"watch_remove": "admin"
|
|
18459
18919
|
};
|
|
@@ -18487,11 +18947,11 @@ function getApiKeyRole(apiKey2, config2) {
|
|
|
18487
18947
|
|
|
18488
18948
|
// src/routes.js
|
|
18489
18949
|
init_constants();
|
|
18490
|
-
var __dirname6 =
|
|
18491
|
-
var htmlDir =
|
|
18950
|
+
var __dirname6 = path18.dirname(fileURLToPath7(import.meta.url));
|
|
18951
|
+
var htmlDir = path18.join(__dirname6, "html");
|
|
18492
18952
|
function loadHtml(name, replacements = {}) {
|
|
18493
18953
|
if (!htmlCache[name]) {
|
|
18494
|
-
htmlCache[name] = fs14.readFileSync(
|
|
18954
|
+
htmlCache[name] = fs14.readFileSync(path18.join(htmlDir, `${name}.html`), "utf-8");
|
|
18495
18955
|
}
|
|
18496
18956
|
let html = htmlCache[name];
|
|
18497
18957
|
for (const [key, value] of Object.entries(replacements)) {
|
|
@@ -18504,7 +18964,7 @@ var cachedToolsJson = null;
|
|
|
18504
18964
|
var cachedToolsJsonAt = 0;
|
|
18505
18965
|
function getToolsJson() {
|
|
18506
18966
|
if (cachedToolsJson && Date.now() - cachedToolsJsonAt < 3e4) return cachedToolsJson;
|
|
18507
|
-
cachedToolsJson = JSON.stringify(
|
|
18967
|
+
cachedToolsJson = JSON.stringify(tools43.map((t) => ({
|
|
18508
18968
|
name: t.name,
|
|
18509
18969
|
description: t.description,
|
|
18510
18970
|
inputSchema: t.inputSchema
|
|
@@ -18534,7 +18994,7 @@ function createJsonBodyParser() {
|
|
|
18534
18994
|
let charset = m ? m[1].toLowerCase() : "utf-8";
|
|
18535
18995
|
const charsetMap = { "gb2312": "gbk", "gb18030": "gbk", "gbk": "gbk", "936": "gbk" };
|
|
18536
18996
|
charset = charsetMap[charset] || charset;
|
|
18537
|
-
const str =
|
|
18997
|
+
const str = iconv2.decode(buf, charset);
|
|
18538
18998
|
req.body = JSON.parse(str);
|
|
18539
18999
|
next();
|
|
18540
19000
|
} catch (e) {
|
|
@@ -18574,15 +19034,45 @@ function createAuthMiddleware() {
|
|
|
18574
19034
|
return res.status(401).json({ error: "Unauthorized" });
|
|
18575
19035
|
};
|
|
18576
19036
|
}
|
|
19037
|
+
function originMatches(pattern, origin) {
|
|
19038
|
+
if (pattern === "*") return true;
|
|
19039
|
+
if (!origin) return false;
|
|
19040
|
+
const getHost = (s) => s.replace(/^https?:\/\//, "").replace(/:\d+$/, "").toLowerCase();
|
|
19041
|
+
const oHost = getHost(origin);
|
|
19042
|
+
let pHost = getHost(pattern);
|
|
19043
|
+
if (pHost.startsWith("*.")) {
|
|
19044
|
+
const suffix = pHost.slice(1);
|
|
19045
|
+
return oHost === suffix.slice(1) || oHost.endsWith(suffix);
|
|
19046
|
+
}
|
|
19047
|
+
return oHost === pHost;
|
|
19048
|
+
}
|
|
18577
19049
|
function createCorsMiddleware() {
|
|
19050
|
+
const allowedOrigins = corsOrigin.split(",").map((s) => s.trim()).filter(Boolean);
|
|
19051
|
+
const allowAll = allowedOrigins.includes("*");
|
|
18578
19052
|
return (req, res, next) => {
|
|
18579
19053
|
if (!enableCors) return next();
|
|
18580
|
-
|
|
19054
|
+
const origin = req.headers.origin;
|
|
19055
|
+
const isPnaPreflight = req.method === "OPTIONS" && req.headers["access-control-request-private-network"] === "true";
|
|
19056
|
+
if (allowAll) {
|
|
19057
|
+
if (isPnaPreflight && origin) {
|
|
19058
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
19059
|
+
res.setHeader("Vary", "Origin");
|
|
19060
|
+
} else {
|
|
19061
|
+
res.setHeader("Access-Control-Allow-Origin", corsOrigin);
|
|
19062
|
+
}
|
|
19063
|
+
} else if (origin && allowedOrigins.some((p) => originMatches(p, origin))) {
|
|
19064
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
19065
|
+
res.setHeader("Vary", "Origin");
|
|
19066
|
+
} else if (!origin) {
|
|
19067
|
+
res.setHeader("Access-Control-Allow-Origin", allowedOrigins[0] || "*");
|
|
19068
|
+
} else {
|
|
19069
|
+
return res.status(403).json({ error: "Origin not allowed" });
|
|
19070
|
+
}
|
|
18581
19071
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, CONNECT");
|
|
18582
19072
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, mcp-session-id, last-event-id");
|
|
18583
19073
|
res.setHeader("Access-Control-Expose-Headers", "mcp-session-id, content-type, x-accel-buffering");
|
|
18584
19074
|
res.setHeader("Access-Control-Max-Age", "86400");
|
|
18585
|
-
res.setHeader("
|
|
19075
|
+
res.setHeader("Access-Control-Allow-Private-Network", "true");
|
|
18586
19076
|
if (req.method === "OPTIONS") return res.status(204).end();
|
|
18587
19077
|
next();
|
|
18588
19078
|
};
|
|
@@ -18673,7 +19163,7 @@ function setupRoutes(app) {
|
|
|
18673
19163
|
},
|
|
18674
19164
|
mcp: {
|
|
18675
19165
|
sessions: sessionServers.size,
|
|
18676
|
-
tools:
|
|
19166
|
+
tools: tools43.length,
|
|
18677
19167
|
sseSessions: sseCount
|
|
18678
19168
|
},
|
|
18679
19169
|
pool: {
|
|
@@ -18683,6 +19173,11 @@ function setupRoutes(app) {
|
|
|
18683
19173
|
}
|
|
18684
19174
|
});
|
|
18685
19175
|
});
|
|
19176
|
+
app.get("/go", (req, res) => {
|
|
19177
|
+
const remoteUrl = "https://atlisp.cn/agent";
|
|
19178
|
+
const cid = config_default.clientId || os10.hostname();
|
|
19179
|
+
res.redirect(302, `${remoteUrl}?clientId=${encodeURIComponent(cid)}`);
|
|
19180
|
+
});
|
|
18686
19181
|
app.get("/health/full", async (req, res) => {
|
|
18687
19182
|
const memUsage = process.memoryUsage();
|
|
18688
19183
|
const poolStats = pool ? pool.getStats() : {};
|
|
@@ -18696,7 +19191,7 @@ function setupRoutes(app) {
|
|
|
18696
19191
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18697
19192
|
cad: { connected: cad.connected, platform: cad.getPlatform?.(), version: cad.getVersion?.(), commandQueueSize: cad._getQueueSize ? cad._getQueueSize() : 0, restartCount: cad._getRestartCount ? cad._getRestartCount() : 0 },
|
|
18698
19193
|
system: { uptime: process.uptime(), memory: { rssMB: Math.round(memUsage.rss / 1024 / 1024), heapUsedMB: Math.round(memUsage.heapUsed / 1024 / 1024), heapTotalMB: Math.round(memUsage.heapTotal / 1024 / 1024) }, cpu: process.cpuUsage() },
|
|
18699
|
-
mcp: { sessions: sessionServers.size, tools:
|
|
19194
|
+
mcp: { sessions: sessionServers.size, tools: tools43.length, sseSessions: sseCount },
|
|
18700
19195
|
pool: poolStats
|
|
18701
19196
|
});
|
|
18702
19197
|
});
|
|
@@ -18734,7 +19229,7 @@ function setupRoutes(app) {
|
|
|
18734
19229
|
app.get("/api/docs", (req, res) => {
|
|
18735
19230
|
const html = loadHtml("api-docs", {
|
|
18736
19231
|
VERSION: SERVER_VERSION,
|
|
18737
|
-
TOOLS_COUNT:
|
|
19232
|
+
TOOLS_COUNT: tools43.length
|
|
18738
19233
|
});
|
|
18739
19234
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
18740
19235
|
res.send(html);
|
|
@@ -18755,7 +19250,7 @@ function setupRoutes(app) {
|
|
|
18755
19250
|
SESSIONS_COUNT: sessionServers.size,
|
|
18756
19251
|
CAD_STATUS_CLASS: cadConnected ? "status-ok" : "status-error",
|
|
18757
19252
|
CAD_STATUS_TEXT: cadStatusText,
|
|
18758
|
-
TOOLS_COUNT:
|
|
19253
|
+
TOOLS_COUNT: tools43.length
|
|
18759
19254
|
});
|
|
18760
19255
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
18761
19256
|
res.send(html);
|
|
@@ -18947,7 +19442,7 @@ function sendWelcome(ws, clientId) {
|
|
|
18947
19442
|
server: { name: SERVER_NAME, version: SERVER_VERSION },
|
|
18948
19443
|
capabilities: SERVER_CAPABILITIES,
|
|
18949
19444
|
clientId,
|
|
18950
|
-
toolCount:
|
|
19445
|
+
toolCount: tools43.length,
|
|
18951
19446
|
cadConnected: cad.connected,
|
|
18952
19447
|
cadPlatform: cad.connected ? cad.getPlatform() : null,
|
|
18953
19448
|
cadVersion: cad.connected ? cad.getVersion() : null
|
|
@@ -19199,9 +19694,9 @@ function createWebSocketServer(httpServer) {
|
|
|
19199
19694
|
// src/plugin-loader.js
|
|
19200
19695
|
init_logger();
|
|
19201
19696
|
import fs15 from "fs";
|
|
19202
|
-
import
|
|
19203
|
-
import
|
|
19204
|
-
var PLUGIN_DIR =
|
|
19697
|
+
import path19 from "path";
|
|
19698
|
+
import os11 from "os";
|
|
19699
|
+
var PLUGIN_DIR = path19.join(os11.homedir(), ".atlisp", "mcp-plugins");
|
|
19205
19700
|
var loadedPlugins = [];
|
|
19206
19701
|
var watchCallbacks = [];
|
|
19207
19702
|
var watcher = null;
|
|
@@ -19226,7 +19721,7 @@ function clearModuleCache(pluginPath) {
|
|
|
19226
19721
|
if (key) delete import.meta[key];
|
|
19227
19722
|
}
|
|
19228
19723
|
async function loadSinglePlugin(file) {
|
|
19229
|
-
const pluginPath =
|
|
19724
|
+
const pluginPath = path19.join(PLUGIN_DIR, file);
|
|
19230
19725
|
clearModuleCache(pluginPath);
|
|
19231
19726
|
try {
|
|
19232
19727
|
const plugin = await import(`${pluginPath}?t=${Date.now()}`);
|
|
@@ -19276,7 +19771,7 @@ function startPluginWatcher() {
|
|
|
19276
19771
|
if (!filename || !filename.endsWith(".js") || filename.startsWith("_")) return;
|
|
19277
19772
|
const existingIndex = loadedPlugins.findIndex((p) => p.name === filename.replace(".js", "") || p._file === filename);
|
|
19278
19773
|
if (eventType === "rename") {
|
|
19279
|
-
const filePath =
|
|
19774
|
+
const filePath = path19.join(PLUGIN_DIR, filename);
|
|
19280
19775
|
if (!fs15.existsSync(filePath)) {
|
|
19281
19776
|
if (existingIndex !== -1) {
|
|
19282
19777
|
loadedPlugins.splice(existingIndex, 1);
|
|
@@ -19316,6 +19811,91 @@ function stopPluginWatcher() {
|
|
|
19316
19811
|
init_tool_registry();
|
|
19317
19812
|
init_mcp_server_state();
|
|
19318
19813
|
|
|
19814
|
+
// src/health-reporter.js
|
|
19815
|
+
init_config();
|
|
19816
|
+
init_cad();
|
|
19817
|
+
init_cad_pool();
|
|
19818
|
+
init_mcp_server_state();
|
|
19819
|
+
init_subscription_manager();
|
|
19820
|
+
init_logger();
|
|
19821
|
+
import os12 from "os";
|
|
19822
|
+
var REPORT_URL = "https://atlisp.cn/api/mcp/health";
|
|
19823
|
+
var REPORT_INTERVAL = 3e4;
|
|
19824
|
+
var intervalHandle = null;
|
|
19825
|
+
function gatherHealth() {
|
|
19826
|
+
let cadResponseTime = 0;
|
|
19827
|
+
if (cad.connected) {
|
|
19828
|
+
const t0 = Date.now();
|
|
19829
|
+
try {
|
|
19830
|
+
cad.ping();
|
|
19831
|
+
} catch {
|
|
19832
|
+
}
|
|
19833
|
+
cadResponseTime = Date.now() - t0;
|
|
19834
|
+
}
|
|
19835
|
+
const memUsage = process.memoryUsage();
|
|
19836
|
+
let sseCount = 0;
|
|
19837
|
+
try {
|
|
19838
|
+
sseCount = sessionManager?.count?.() || 0;
|
|
19839
|
+
} catch {
|
|
19840
|
+
}
|
|
19841
|
+
return {
|
|
19842
|
+
clientId: config_default.clientId || os12.hostname(),
|
|
19843
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19844
|
+
status: "ok",
|
|
19845
|
+
cad: {
|
|
19846
|
+
connected: cad.connected,
|
|
19847
|
+
platform: cad.getPlatform ? cad.getPlatform() : null,
|
|
19848
|
+
version: cad.getVersion ? cad.getVersion() : null,
|
|
19849
|
+
responseTime: cadResponseTime,
|
|
19850
|
+
commandQueueSize: cad._getQueueSize ? cad._getQueueSize() : 0,
|
|
19851
|
+
restartCount: cad._getRestartCount ? cad._getRestartCount() : 0
|
|
19852
|
+
},
|
|
19853
|
+
system: {
|
|
19854
|
+
uptime: process.uptime(),
|
|
19855
|
+
memory: {
|
|
19856
|
+
rss: Math.round(memUsage.rss / 1024 / 1024),
|
|
19857
|
+
heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
|
|
19858
|
+
heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024)
|
|
19859
|
+
}
|
|
19860
|
+
},
|
|
19861
|
+
mcp: {
|
|
19862
|
+
sessions: sessionServers.size,
|
|
19863
|
+
sseSessions: sseCount
|
|
19864
|
+
},
|
|
19865
|
+
pool: pool ? {
|
|
19866
|
+
total: pool.getStats().total,
|
|
19867
|
+
active: pool.getStats().active,
|
|
19868
|
+
instances: pool.getStats().instances
|
|
19869
|
+
} : null
|
|
19870
|
+
};
|
|
19871
|
+
}
|
|
19872
|
+
async function report() {
|
|
19873
|
+
try {
|
|
19874
|
+
const data = gatherHealth();
|
|
19875
|
+
const res = await fetch(REPORT_URL, {
|
|
19876
|
+
method: "POST",
|
|
19877
|
+
headers: { "Content-Type": "application/json" },
|
|
19878
|
+
body: JSON.stringify(data),
|
|
19879
|
+
signal: AbortSignal.timeout(1e4)
|
|
19880
|
+
});
|
|
19881
|
+
if (!res.ok) {
|
|
19882
|
+
error(`Health report failed: ${res.status}`);
|
|
19883
|
+
}
|
|
19884
|
+
} catch (e) {
|
|
19885
|
+
error(`Health report error: ${e.message}`);
|
|
19886
|
+
}
|
|
19887
|
+
}
|
|
19888
|
+
function startHealthReporter() {
|
|
19889
|
+
report();
|
|
19890
|
+
intervalHandle = setInterval(report, REPORT_INTERVAL);
|
|
19891
|
+
}
|
|
19892
|
+
function stopHealthReporter() {
|
|
19893
|
+
if (intervalHandle) {
|
|
19894
|
+
clearInterval(intervalHandle);
|
|
19895
|
+
intervalHandle = null;
|
|
19896
|
+
}
|
|
19897
|
+
}
|
|
19898
|
+
|
|
19319
19899
|
// src/streamable-http.js
|
|
19320
19900
|
init_logger();
|
|
19321
19901
|
init_mcp_handlers();
|
|
@@ -19326,7 +19906,7 @@ var mcpServer = null;
|
|
|
19326
19906
|
var streamableTransport = null;
|
|
19327
19907
|
async function initStreamableHttpServer() {
|
|
19328
19908
|
if (mcpServer) return;
|
|
19329
|
-
mcpServer = createMcpServer({ tools:
|
|
19909
|
+
mcpServer = createMcpServer({ tools: tools43, handleToolCall });
|
|
19330
19910
|
streamableTransport = new StreamableHTTPServerTransport2({
|
|
19331
19911
|
sessionIdGenerator: () => randomUUID8()
|
|
19332
19912
|
});
|
|
@@ -19377,9 +19957,9 @@ function setupStreamableHttpRoutes(app) {
|
|
|
19377
19957
|
init_mcp_tools();
|
|
19378
19958
|
init_function_handlers();
|
|
19379
19959
|
init_constants();
|
|
19380
|
-
var __dirname7 =
|
|
19960
|
+
var __dirname7 = path20.dirname(fileURLToPath8(import.meta.url));
|
|
19381
19961
|
var require3 = createRequire2(import.meta.url);
|
|
19382
|
-
var { version: version2 } = require3(
|
|
19962
|
+
var { version: version2 } = require3(path20.join(__dirname7, "..", "package.json"));
|
|
19383
19963
|
var isMcpScript = process.argv[1]?.includes("atlisp-mcp");
|
|
19384
19964
|
if (isMcpScript) {
|
|
19385
19965
|
const cliArgs2 = process.argv.slice(2);
|
|
@@ -19413,6 +19993,7 @@ Options:
|
|
|
19413
19993
|
--no-lint Disable lint pre-check for eval_lisp
|
|
19414
19994
|
--lint-off Same as --no-lint
|
|
19415
19995
|
--api-key <key> API key for authentication
|
|
19996
|
+
--client-id <id> Client identifier for remote health report
|
|
19416
19997
|
--security-level <type> Security level: strict, standard, relaxed (default: strict)
|
|
19417
19998
|
|
|
19418
19999
|
Environment Variables:
|
|
@@ -19433,7 +20014,8 @@ Environment Variables:
|
|
|
19433
20014
|
LINT_LEVEL Lint level (error/warn/off)
|
|
19434
20015
|
NO_LINT Disable lint (true/false)
|
|
19435
20016
|
REQUEST_LOG_ENABLED Enable request logging (true/false, default: true)
|
|
19436
|
-
CORS_ORIGIN CORS origin (default:
|
|
20017
|
+
CORS_ORIGIN CORS origin (default: https://atlisp.cn)
|
|
20018
|
+
CLIENT_ID Client identifier for remote health report
|
|
19437
20019
|
RATE_LIMIT_WINDOW Rate limit window in ms (default: 60000)
|
|
19438
20020
|
RATE_LIMIT_MAX Max requests per window (default: 100)
|
|
19439
20021
|
|
|
@@ -19489,6 +20071,8 @@ For more info: https://atlisp.cn
|
|
|
19489
20071
|
process.env.SSL_CERT_PATH = cliArgs2[++i];
|
|
19490
20072
|
} else if (arg === "--api-key" && cliArgs2[i + 1]) {
|
|
19491
20073
|
process.env.MCP_API_KEY = cliArgs2[++i];
|
|
20074
|
+
} else if (arg === "--client-id" && cliArgs2[i + 1]) {
|
|
20075
|
+
process.env.CLIENT_ID = cliArgs2[++i];
|
|
19492
20076
|
} else if (arg === "--metrics-enabled" && cliArgs2[i + 1]) {
|
|
19493
20077
|
process.env.METRICS_ENABLED = cliArgs2[++i];
|
|
19494
20078
|
}
|
|
@@ -19511,7 +20095,7 @@ async function initCadConnection() {
|
|
|
19511
20095
|
}
|
|
19512
20096
|
async function startServer() {
|
|
19513
20097
|
await loadPlugins();
|
|
19514
|
-
initPlugins({ cad, config: config_default, log, registerTool, tools:
|
|
20098
|
+
initPlugins({ cad, config: config_default, log, registerTool, tools: tools43 });
|
|
19515
20099
|
onPluginChange((type, name) => {
|
|
19516
20100
|
log(`Plugin changed: ${type} ${name}`);
|
|
19517
20101
|
broadcastToolListChanged();
|
|
@@ -19521,7 +20105,7 @@ async function startServer() {
|
|
|
19521
20105
|
startPluginWatcher();
|
|
19522
20106
|
let promptsWatcher = null;
|
|
19523
20107
|
try {
|
|
19524
|
-
const promptsDir =
|
|
20108
|
+
const promptsDir = path20.join(__dirname7, "..", "prompts");
|
|
19525
20109
|
if (fs16.existsSync(promptsDir)) {
|
|
19526
20110
|
promptsWatcher = fs16.watch(promptsDir, (eventType, filename) => {
|
|
19527
20111
|
if (filename && filename.endsWith(".json")) {
|
|
@@ -19535,7 +20119,7 @@ async function startServer() {
|
|
|
19535
20119
|
}
|
|
19536
20120
|
if (config_default.transport === "stdio") {
|
|
19537
20121
|
await initCadConnection();
|
|
19538
|
-
const mcpServer2 = createStdioServer({ tools:
|
|
20122
|
+
const mcpServer2 = createStdioServer({ tools: tools43, handleToolCall });
|
|
19539
20123
|
const transport = new StdioServerTransport();
|
|
19540
20124
|
const sessionId = "stdio-session";
|
|
19541
20125
|
sessionManager.createSession(sessionId);
|
|
@@ -19583,10 +20167,12 @@ async function startServer() {
|
|
|
19583
20167
|
const proto = useSsl ? "https" : "http";
|
|
19584
20168
|
const mode = config_default.transport === "ws" ? "WebSocket" : config_default.transport === "streamable-http" ? "Streamable HTTP" : "\u591A\u4F1A\u8BDD";
|
|
19585
20169
|
console.error(`@lisp MCP Server \u542F\u52A8 - ${proto}://${config_default.host}:${config_default.port} (${mode}\u6A21\u5F0F)`);
|
|
20170
|
+
startHealthReporter();
|
|
19586
20171
|
});
|
|
19587
20172
|
async function shutdown(signal) {
|
|
19588
20173
|
console.error(`
|
|
19589
20174
|
\u6536\u5230 ${signal}\uFF0C\u6B63\u5728\u4F18\u96C5\u5173\u95ED...`);
|
|
20175
|
+
stopHealthReporter();
|
|
19590
20176
|
stopPluginWatcher();
|
|
19591
20177
|
if (promptsWatcher) {
|
|
19592
20178
|
promptsWatcher.close();
|
|
@@ -19636,5 +20222,5 @@ export {
|
|
|
19636
20222
|
handleToolCall,
|
|
19637
20223
|
loadAtlibFunctionLib,
|
|
19638
20224
|
startServer,
|
|
19639
|
-
|
|
20225
|
+
tools43 as tools
|
|
19640
20226
|
};
|