@atlisp/mcp 1.8.23 → 1.8.25
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 +1422 -848
- package/dist/cad-rothelper.dll +0 -0
- package/dist/cad-worker.js +236 -174
- package/dist/config.js +59 -56
- 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/pipelines/analyze-and-report.json +0 -16
- package/dist/pipelines/batch-export-pdfs.json +0 -11
- package/dist/pipelines/batch-layer-move.json +0 -19
- package/dist/pipelines/export-current-drawing.json +0 -18
- package/dist/pipelines/purge-and-save.json +0 -16
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;
|
|
@@ -845,21 +926,8 @@ var init_cad = __esm({
|
|
|
845
926
|
return `Platform: ${this._product}, Version: ${this._version}, Status: Connected`;
|
|
846
927
|
}
|
|
847
928
|
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();
|
|
929
|
+
this._reset();
|
|
930
|
+
this._cb.reset();
|
|
863
931
|
}
|
|
864
932
|
async ping() {
|
|
865
933
|
try {
|
|
@@ -878,12 +946,6 @@ var init_cad = __esm({
|
|
|
878
946
|
this._activeDocName = null;
|
|
879
947
|
this._monitorStarted = false;
|
|
880
948
|
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
949
|
this._resetWorker();
|
|
888
950
|
}
|
|
889
951
|
_getQueueSize() {
|
|
@@ -892,44 +954,6 @@ var init_cad = __esm({
|
|
|
892
954
|
_getRestartCount() {
|
|
893
955
|
return this._restartCount;
|
|
894
956
|
}
|
|
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
957
|
_spawnWorker(type) {
|
|
934
958
|
const w = spawn("node", [workerPath], { stdio: ["pipe", "pipe", "pipe"] });
|
|
935
959
|
w.connected = true;
|
|
@@ -940,7 +964,7 @@ var init_cad = __esm({
|
|
|
940
964
|
w.connected = false;
|
|
941
965
|
if (type === "primary") {
|
|
942
966
|
if (w !== this._primaryWorker) return;
|
|
943
|
-
this.
|
|
967
|
+
this._cb.recordFailure();
|
|
944
968
|
const exitError = new Error(`Primary worker exited with code ${code}`);
|
|
945
969
|
for (const [id, entry] of this._pendingRequests) {
|
|
946
970
|
clearTimeout(entry.timeout);
|
|
@@ -977,7 +1001,7 @@ var init_cad = __esm({
|
|
|
977
1001
|
this._primaryWorker = null;
|
|
978
1002
|
}
|
|
979
1003
|
this._primaryWorker = this._spawnWorker("primary");
|
|
980
|
-
this.
|
|
1004
|
+
this._cb.recordSuccess();
|
|
981
1005
|
if (!this._heartbeatTimer) this._startHeartbeat();
|
|
982
1006
|
this._restartCount = 0;
|
|
983
1007
|
}
|
|
@@ -1118,14 +1142,9 @@ var init_cad = __esm({
|
|
|
1118
1142
|
}, delay);
|
|
1119
1143
|
}
|
|
1120
1144
|
async _sendMessage(msg) {
|
|
1121
|
-
if (!this.
|
|
1145
|
+
if (!this._cb.allowRequest()) {
|
|
1122
1146
|
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
|
-
}
|
|
1147
|
+
this._cb.reset();
|
|
1129
1148
|
await this._resetWorker();
|
|
1130
1149
|
await this._getWorker(false);
|
|
1131
1150
|
}
|
|
@@ -1141,17 +1160,17 @@ var init_cad = __esm({
|
|
|
1141
1160
|
const p = self._pendingRequests.get(requestId);
|
|
1142
1161
|
if (p) {
|
|
1143
1162
|
self._pendingRequests.delete(requestId);
|
|
1144
|
-
if (!noCircuitBreaker) self.
|
|
1163
|
+
if (!noCircuitBreaker) self._cb.recordFailure();
|
|
1145
1164
|
reject(new Error("Timeout waiting for worker"));
|
|
1146
1165
|
}
|
|
1147
1166
|
}, MESSAGE_TIMEOUT);
|
|
1148
1167
|
const entry = {
|
|
1149
1168
|
resolve: (v) => {
|
|
1150
|
-
if (!noCircuitBreaker && !entry._skipCb) self.
|
|
1169
|
+
if (!noCircuitBreaker && !entry._skipCb) self._cb.recordSuccess();
|
|
1151
1170
|
resolve(v);
|
|
1152
1171
|
},
|
|
1153
1172
|
reject: (e) => {
|
|
1154
|
-
if (!noCircuitBreaker && !entry._skipCb) self.
|
|
1173
|
+
if (!noCircuitBreaker && !entry._skipCb) self._cb.recordFailure();
|
|
1155
1174
|
reject(e);
|
|
1156
1175
|
},
|
|
1157
1176
|
timeout
|
|
@@ -1162,11 +1181,15 @@ var init_cad = __esm({
|
|
|
1162
1181
|
} catch (e) {
|
|
1163
1182
|
clearTimeout(timeout);
|
|
1164
1183
|
self._pendingRequests.delete(requestId);
|
|
1165
|
-
if (!noCircuitBreaker) self.
|
|
1184
|
+
if (!noCircuitBreaker) self._cb.recordFailure();
|
|
1166
1185
|
reject(new Error(`Failed to write to worker: ${e.message}`));
|
|
1167
1186
|
}
|
|
1168
1187
|
});
|
|
1169
1188
|
}
|
|
1189
|
+
_isReadOnlyMessage(msg) {
|
|
1190
|
+
if (msg.code) return isReadCommand(msg.code);
|
|
1191
|
+
return false;
|
|
1192
|
+
}
|
|
1170
1193
|
};
|
|
1171
1194
|
_activeConnection = new CadConnection();
|
|
1172
1195
|
_resolveInstanceConn = null;
|
|
@@ -1175,28 +1198,28 @@ var init_cad = __esm({
|
|
|
1175
1198
|
return _resolveConn().connected;
|
|
1176
1199
|
},
|
|
1177
1200
|
set connected(v) {
|
|
1178
|
-
|
|
1201
|
+
_resolveConn().connected = v;
|
|
1179
1202
|
},
|
|
1180
1203
|
get version() {
|
|
1181
|
-
return
|
|
1204
|
+
return _resolveConn()._version;
|
|
1182
1205
|
},
|
|
1183
1206
|
set version(v) {
|
|
1184
|
-
|
|
1207
|
+
_resolveConn()._version = v;
|
|
1185
1208
|
},
|
|
1186
1209
|
get product() {
|
|
1187
|
-
return
|
|
1210
|
+
return _resolveConn()._product;
|
|
1188
1211
|
},
|
|
1189
1212
|
set product(v) {
|
|
1190
|
-
|
|
1213
|
+
_resolveConn()._product = v;
|
|
1191
1214
|
},
|
|
1192
1215
|
get _platform() {
|
|
1193
|
-
return
|
|
1216
|
+
return _resolveConn()._platform;
|
|
1194
1217
|
},
|
|
1195
1218
|
set _platform(v) {
|
|
1196
|
-
|
|
1219
|
+
_resolveConn()._platform = v;
|
|
1197
1220
|
},
|
|
1198
1221
|
async connect(platform) {
|
|
1199
|
-
return
|
|
1222
|
+
return _resolveConn().connect(platform);
|
|
1200
1223
|
},
|
|
1201
1224
|
async sendCommand(code) {
|
|
1202
1225
|
return _resolveConn().sendCommand(code);
|
|
@@ -1205,49 +1228,49 @@ var init_cad = __esm({
|
|
|
1205
1228
|
return _resolveConn().sendCommandWithResult(code, encoding);
|
|
1206
1229
|
},
|
|
1207
1230
|
getVersion() {
|
|
1208
|
-
return
|
|
1231
|
+
return _resolveConn().getVersion();
|
|
1209
1232
|
},
|
|
1210
1233
|
getPlatform() {
|
|
1211
|
-
return
|
|
1234
|
+
return _resolveConn().getPlatform();
|
|
1212
1235
|
},
|
|
1213
1236
|
getConnectionId() {
|
|
1214
|
-
return
|
|
1237
|
+
return _resolveConn().getConnectionId();
|
|
1215
1238
|
},
|
|
1216
1239
|
isAvailable() {
|
|
1217
|
-
return
|
|
1240
|
+
return _resolveConn().isAvailable();
|
|
1218
1241
|
},
|
|
1219
1242
|
async isBusy() {
|
|
1220
|
-
return
|
|
1243
|
+
return _resolveConn().isBusy();
|
|
1221
1244
|
},
|
|
1222
1245
|
async hasDoc() {
|
|
1223
|
-
return
|
|
1246
|
+
return _resolveConn().hasDoc();
|
|
1224
1247
|
},
|
|
1225
1248
|
async newDoc() {
|
|
1226
|
-
return
|
|
1249
|
+
return _resolveConn().newDoc();
|
|
1227
1250
|
},
|
|
1228
1251
|
async bringToFront() {
|
|
1229
|
-
return
|
|
1252
|
+
return _resolveConn().bringToFront();
|
|
1230
1253
|
},
|
|
1231
1254
|
async getActiveDocInfo() {
|
|
1232
|
-
return
|
|
1255
|
+
return _resolveConn().getActiveDocInfo();
|
|
1233
1256
|
},
|
|
1234
1257
|
async getInfo() {
|
|
1235
|
-
return
|
|
1258
|
+
return _resolveConn().getInfo();
|
|
1236
1259
|
},
|
|
1237
1260
|
async disconnect() {
|
|
1238
|
-
return
|
|
1261
|
+
return _resolveConn().disconnect();
|
|
1239
1262
|
},
|
|
1240
1263
|
async ping() {
|
|
1241
|
-
return
|
|
1264
|
+
return _resolveConn().ping();
|
|
1242
1265
|
},
|
|
1243
1266
|
_reset() {
|
|
1244
|
-
return
|
|
1267
|
+
return _resolveConn()._reset();
|
|
1245
1268
|
},
|
|
1246
1269
|
_getQueueSize() {
|
|
1247
|
-
return
|
|
1270
|
+
return _resolveConn()._getQueueSize();
|
|
1248
1271
|
},
|
|
1249
1272
|
_getRestartCount() {
|
|
1250
|
-
return
|
|
1273
|
+
return _resolveConn()._getRestartCount();
|
|
1251
1274
|
}
|
|
1252
1275
|
};
|
|
1253
1276
|
cad_default = CadConnection;
|
|
@@ -1258,7 +1281,7 @@ var init_cad = __esm({
|
|
|
1258
1281
|
import path3 from "path";
|
|
1259
1282
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1260
1283
|
import { createRequire } from "module";
|
|
1261
|
-
var CAD_PLATFORMS, FILE_EXTENSIONS, __dirname2, require2, version, SERVER_NAME, SERVER_VERSION, SERVER_CAPABILITIES, MOCK_PACKAGES;
|
|
1284
|
+
var CAD_PLATFORMS, FILE_EXTENSIONS, __dirname2, require2, version, SERVER_NAME, SERVER_VERSION, SERVER_CAPABILITIES, MOCK_PACKAGES, CAD_RESOURCE_URIS;
|
|
1262
1285
|
var init_constants = __esm({
|
|
1263
1286
|
"src/constants.js"() {
|
|
1264
1287
|
CAD_PLATFORMS = ["AutoCAD", "ZWCAD", "GStarCAD", "BricsCAD"];
|
|
@@ -1281,6 +1304,17 @@ var init_constants = __esm({
|
|
|
1281
1304
|
completions: {}
|
|
1282
1305
|
};
|
|
1283
1306
|
MOCK_PACKAGES = [];
|
|
1307
|
+
CAD_RESOURCE_URIS = [
|
|
1308
|
+
"atlisp://cad/info",
|
|
1309
|
+
"atlisp://dwg/name",
|
|
1310
|
+
"atlisp://dwg/path",
|
|
1311
|
+
"atlisp://dwg/entities",
|
|
1312
|
+
"atlisp://dwg/tbl",
|
|
1313
|
+
"atlisp://dwg/block-refs",
|
|
1314
|
+
"atlisp://dwg/text-content",
|
|
1315
|
+
"atlisp://cad/dwgs",
|
|
1316
|
+
"atlisp://packages"
|
|
1317
|
+
];
|
|
1284
1318
|
}
|
|
1285
1319
|
});
|
|
1286
1320
|
|
|
@@ -1481,7 +1515,10 @@ var init_resource_defs = __esm({
|
|
|
1481
1515
|
{ uri: "atlisp://standards/drafting", name: "Drafting Standards", description: "CAD \u5236\u56FE\u89C4\u8303", mimeType: "application/json", subscribable: false },
|
|
1482
1516
|
{ uri: "atlisp://standards/coding", name: "Coding Standards", description: "@lisp \u7F16\u7801\u89C4\u8303", mimeType: "application/json", subscribable: false },
|
|
1483
1517
|
{ 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 }
|
|
1518
|
+
{ 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 },
|
|
1519
|
+
{ 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 },
|
|
1520
|
+
{ 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 },
|
|
1521
|
+
{ 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
1522
|
];
|
|
1486
1523
|
TBL_QUERIES = {
|
|
1487
1524
|
layer: { name: "layer", lisp: `(progn
|
|
@@ -1528,49 +1565,70 @@ var init_resource_defs = __esm({
|
|
|
1528
1565
|
});
|
|
1529
1566
|
|
|
1530
1567
|
// src/handlers/resource-cache.js
|
|
1568
|
+
function _getCache() {
|
|
1569
|
+
const key = _instanceKey || _defaultKey;
|
|
1570
|
+
if (!_instanceCaches.has(key)) {
|
|
1571
|
+
_instanceCaches.set(key, /* @__PURE__ */ new Map());
|
|
1572
|
+
}
|
|
1573
|
+
return _instanceCaches.get(key);
|
|
1574
|
+
}
|
|
1575
|
+
function _ttl() {
|
|
1576
|
+
return config_default.resourceCacheTtl;
|
|
1577
|
+
}
|
|
1531
1578
|
function ensureCleanup() {
|
|
1532
1579
|
if (cleanupTimer) return;
|
|
1533
1580
|
cleanupTimer = setInterval(() => {
|
|
1534
1581
|
const now = Date.now();
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1582
|
+
const ttl = _ttl();
|
|
1583
|
+
for (const cache of _instanceCaches.values()) {
|
|
1584
|
+
for (const [key, entry] of cache) {
|
|
1585
|
+
if (now - entry.timestamp >= ttl) {
|
|
1586
|
+
cache.delete(key);
|
|
1587
|
+
}
|
|
1538
1588
|
}
|
|
1539
1589
|
}
|
|
1540
1590
|
}, CLEANUP_INTERVAL);
|
|
1541
1591
|
cleanupTimer.unref();
|
|
1542
1592
|
}
|
|
1593
|
+
function setInstanceKey(key) {
|
|
1594
|
+
_instanceKey = key || null;
|
|
1595
|
+
}
|
|
1543
1596
|
function getCached(key) {
|
|
1544
|
-
const
|
|
1545
|
-
|
|
1597
|
+
const cache = _getCache();
|
|
1598
|
+
const entry = cache.get(key);
|
|
1599
|
+
if (entry && Date.now() - entry.timestamp < _ttl()) {
|
|
1546
1600
|
return entry.data;
|
|
1547
1601
|
}
|
|
1548
|
-
|
|
1602
|
+
cache.delete(key);
|
|
1549
1603
|
return null;
|
|
1550
1604
|
}
|
|
1551
1605
|
function setCache(key, data) {
|
|
1552
|
-
|
|
1606
|
+
_getCache().set(key, { data, timestamp: Date.now() });
|
|
1553
1607
|
}
|
|
1554
1608
|
function clearCache(uri) {
|
|
1555
|
-
const
|
|
1556
|
-
if (
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1609
|
+
const basePrefix = URI_CACHE_PREFIX[uri];
|
|
1610
|
+
if (basePrefix) {
|
|
1611
|
+
const cache = _getCache();
|
|
1612
|
+
for (const key of cache.keys()) {
|
|
1613
|
+
if (key === basePrefix || key.startsWith(basePrefix + ":")) {
|
|
1614
|
+
cache.delete(key);
|
|
1560
1615
|
}
|
|
1561
1616
|
}
|
|
1562
1617
|
} else if (!uri) {
|
|
1563
|
-
|
|
1618
|
+
const key = _instanceKey || _defaultKey;
|
|
1619
|
+
_instanceCaches.delete(key);
|
|
1620
|
+
_instanceCaches.set(key, /* @__PURE__ */ new Map());
|
|
1564
1621
|
}
|
|
1565
1622
|
}
|
|
1566
|
-
var
|
|
1623
|
+
var CLEANUP_INTERVAL, cleanupTimer, _instanceKey, _instanceCaches, _defaultKey, URI_CACHE_PREFIX;
|
|
1567
1624
|
var init_resource_cache = __esm({
|
|
1568
1625
|
"src/handlers/resource-cache.js"() {
|
|
1569
1626
|
init_config();
|
|
1570
|
-
CACHE_TTL = config_default.resourceCacheTtl;
|
|
1571
|
-
resourceCache = /* @__PURE__ */ new Map();
|
|
1572
1627
|
CLEANUP_INTERVAL = 6e4;
|
|
1573
1628
|
cleanupTimer = null;
|
|
1629
|
+
_instanceKey = null;
|
|
1630
|
+
_instanceCaches = /* @__PURE__ */ new Map();
|
|
1631
|
+
_defaultKey = "__default__";
|
|
1574
1632
|
ensureCleanup();
|
|
1575
1633
|
URI_CACHE_PREFIX = {
|
|
1576
1634
|
"atlisp://cad/info": "cad:info",
|
|
@@ -1591,6 +1649,23 @@ function createError(code, details = {}) {
|
|
|
1591
1649
|
const def = ERROR_DEFS[code] || ERROR_DEFS[ERROR_CODES.INTERNAL_ERROR];
|
|
1592
1650
|
return new MCPError(code, def.message, details);
|
|
1593
1651
|
}
|
|
1652
|
+
function toMcpError(error2) {
|
|
1653
|
+
if (error2 instanceof MCPError) return error2;
|
|
1654
|
+
if (error2 instanceof Error) {
|
|
1655
|
+
return new MCPError(ERROR_CODES.INTERNAL_ERROR, error2.message, { stack: error2.stack });
|
|
1656
|
+
}
|
|
1657
|
+
return new MCPError(ERROR_CODES.INTERNAL_ERROR, String(error2));
|
|
1658
|
+
}
|
|
1659
|
+
function mcpErrorResponse(error2) {
|
|
1660
|
+
const mcpErr = toMcpError(error2);
|
|
1661
|
+
const json = mcpErr.toJSON();
|
|
1662
|
+
return {
|
|
1663
|
+
content: [{ type: "text", text: `[${json.code}] ${json.message}
|
|
1664
|
+
\u63D0\u793A: ${json.hint}
|
|
1665
|
+
\u5EFA\u8BAE\u5DE5\u5177: ${json.suggestedTools.join(", ") || "\u65E0"}` }],
|
|
1666
|
+
isError: true
|
|
1667
|
+
};
|
|
1668
|
+
}
|
|
1594
1669
|
function mcpSuccessResponse(text) {
|
|
1595
1670
|
return { content: [{ type: "text", text: String(text) }] };
|
|
1596
1671
|
}
|
|
@@ -1604,9 +1679,14 @@ var init_errors = __esm({
|
|
|
1604
1679
|
LISP_PAREN_MISMATCH: "LISP_PAREN_MISMATCH",
|
|
1605
1680
|
TIMEOUT: "TIMEOUT",
|
|
1606
1681
|
INVALID_PARAMS: "INVALID_PARAMS",
|
|
1682
|
+
INVALID_ARGS: "INVALID_ARGS",
|
|
1607
1683
|
METHOD_NOT_FOUND: "METHOD_NOT_FOUND",
|
|
1684
|
+
HANDLER_NOT_FOUND: "HANDLER_NOT_FOUND",
|
|
1608
1685
|
RESOURCE_NOT_FOUND: "RESOURCE_NOT_FOUND",
|
|
1609
1686
|
PACKAGE_NOT_FOUND: "PACKAGE_NOT_FOUND",
|
|
1687
|
+
OPERATION_FAILED: "OPERATION_FAILED",
|
|
1688
|
+
RATE_LIMITED: "RATE_LIMITED",
|
|
1689
|
+
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
1610
1690
|
INTERNAL_ERROR: "INTERNAL_ERROR"
|
|
1611
1691
|
};
|
|
1612
1692
|
ERROR_DEFS = {
|
|
@@ -1640,6 +1720,31 @@ var init_errors = __esm({
|
|
|
1640
1720
|
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
1721
|
tools: ["search_tools", "list_tools_by_category"]
|
|
1642
1722
|
},
|
|
1723
|
+
[ERROR_CODES.INVALID_ARGS]: {
|
|
1724
|
+
message: "\u53C2\u6570\u6821\u9A8C\u5931\u8D25",
|
|
1725
|
+
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",
|
|
1726
|
+
tools: ["search_tools", "list_tools_by_category"]
|
|
1727
|
+
},
|
|
1728
|
+
[ERROR_CODES.HANDLER_NOT_FOUND]: {
|
|
1729
|
+
message: "\u5DE5\u5177\u672A\u627E\u5230",
|
|
1730
|
+
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",
|
|
1731
|
+
tools: ["search_tools", "list_tools_by_category"]
|
|
1732
|
+
},
|
|
1733
|
+
[ERROR_CODES.OPERATION_FAILED]: {
|
|
1734
|
+
message: "\u64CD\u4F5C\u6267\u884C\u5931\u8D25",
|
|
1735
|
+
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",
|
|
1736
|
+
tools: ["get_system_status", "get_cad_info"]
|
|
1737
|
+
},
|
|
1738
|
+
[ERROR_CODES.RATE_LIMITED]: {
|
|
1739
|
+
message: "\u8C03\u7528\u9891\u7387\u8D85\u9650",
|
|
1740
|
+
hint: "\u5DE5\u5177\u8C03\u7528\u8FC7\u4E8E\u9891\u7E41\u3002\u8BF7\u7B49\u5F85\u4E00\u6BB5\u65F6\u95F4\u540E\u518D\u8BD5",
|
|
1741
|
+
tools: []
|
|
1742
|
+
},
|
|
1743
|
+
[ERROR_CODES.SESSION_NOT_FOUND]: {
|
|
1744
|
+
message: "\u4F1A\u8BDD\u672A\u627E\u5230",
|
|
1745
|
+
hint: "\u6307\u5B9A ID \u7684\u4F1A\u8BDD\u4E0D\u5B58\u5728\u3002\u8BF7\u68C0\u67E5 sessionId \u53C2\u6570\u662F\u5426\u6B63\u786E",
|
|
1746
|
+
tools: ["lisp_repl_list"]
|
|
1747
|
+
},
|
|
1643
1748
|
[ERROR_CODES.METHOD_NOT_FOUND]: {
|
|
1644
1749
|
message: "\u65B9\u6CD5\u4E0D\u5B58\u5728",
|
|
1645
1750
|
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 +1889,8 @@ __export(renderer_exports, {
|
|
|
1784
1889
|
renderPrompt: () => renderPrompt,
|
|
1785
1890
|
renderTemplate: () => renderTemplate
|
|
1786
1891
|
});
|
|
1787
|
-
function resolvePath(obj,
|
|
1788
|
-
const parts =
|
|
1892
|
+
function resolvePath(obj, path21) {
|
|
1893
|
+
const parts = path21.split(/[.\[\]]/g).filter(Boolean);
|
|
1789
1894
|
let val = obj;
|
|
1790
1895
|
for (const p of parts) {
|
|
1791
1896
|
if (val == null) return void 0;
|
|
@@ -1795,8 +1900,8 @@ function resolvePath(obj, path20) {
|
|
|
1795
1900
|
}
|
|
1796
1901
|
function renderTemplate(template, args) {
|
|
1797
1902
|
return template.replace(PARAM_RE, (match, rawExpr, expr) => {
|
|
1798
|
-
const
|
|
1799
|
-
const val = resolvePath(args,
|
|
1903
|
+
const path21 = rawExpr || expr;
|
|
1904
|
+
const val = resolvePath(args, path21);
|
|
1800
1905
|
if (val == null) return "";
|
|
1801
1906
|
const strVal = String(val);
|
|
1802
1907
|
if (rawExpr) return strVal;
|
|
@@ -2228,8 +2333,8 @@ var init_sse_session = __esm({
|
|
|
2228
2333
|
sendMessage(data) {
|
|
2229
2334
|
return this.sendEvent(SSE_EVENTS.MESSAGE, data);
|
|
2230
2335
|
}
|
|
2231
|
-
sendEndpoint(
|
|
2232
|
-
return this.sendEvent(SSE_EVENTS.ENDPOINT,
|
|
2336
|
+
sendEndpoint(path21) {
|
|
2337
|
+
return this.sendEvent(SSE_EVENTS.ENDPOINT, path21);
|
|
2233
2338
|
}
|
|
2234
2339
|
sendError(code, message, id = null) {
|
|
2235
2340
|
return this.sendEvent(SSE_EVENTS.ERROR, { code, message }, id);
|
|
@@ -2951,7 +3056,8 @@ var init_info_tools = __esm({
|
|
|
2951
3056
|
}
|
|
2952
3057
|
},
|
|
2953
3058
|
{ 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)" } } } }
|
|
3059
|
+
{ 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)" } } } },
|
|
3060
|
+
{ 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
3061
|
];
|
|
2956
3062
|
}
|
|
2957
3063
|
});
|
|
@@ -5492,12 +5598,12 @@ var init_pool_tools = __esm({
|
|
|
5492
5598
|
inputSchema: {
|
|
5493
5599
|
type: "object",
|
|
5494
5600
|
properties: {
|
|
5495
|
-
key: { type: "string", description: "\u5B9E\u4F8B\u6807\u8BC6\u952E\u540D\uFF08\u5982 autocad, zwcad, mycad\uFF09" },
|
|
5601
|
+
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
5602
|
platform: { type: "string", description: "CAD \u5E73\u53F0: AutoCAD, ZWCAD, GStarCAD, BricsCAD\uFF08\u53EF\u9009\uFF0C\u81EA\u52A8\u68C0\u6D4B\uFF09" },
|
|
5603
|
+
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
5604
|
label: { type: "string", description: "\u5B9E\u4F8B\u663E\u793A\u6807\u7B7E\uFF08\u53EF\u9009\uFF09" },
|
|
5498
5605
|
makeActive: { type: "boolean", description: "\u8FDE\u63A5\u540E\u8BBE\u4E3A\u6D3B\u52A8\u5B9E\u4F8B\uFF08\u9ED8\u8BA4 true\uFF09" }
|
|
5499
|
-
}
|
|
5500
|
-
required: ["key"]
|
|
5606
|
+
}
|
|
5501
5607
|
}
|
|
5502
5608
|
},
|
|
5503
5609
|
{
|
|
@@ -6457,7 +6563,66 @@ var init_debug_tools = __esm({
|
|
|
6457
6563
|
}
|
|
6458
6564
|
});
|
|
6459
6565
|
|
|
6566
|
+
// src/tools/concurrent-tools.js
|
|
6567
|
+
var tools42;
|
|
6568
|
+
var init_concurrent_tools = __esm({
|
|
6569
|
+
"src/tools/concurrent-tools.js"() {
|
|
6570
|
+
tools42 = [
|
|
6571
|
+
{
|
|
6572
|
+
name: "batch_concurrent_tasks",
|
|
6573
|
+
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",
|
|
6574
|
+
inputSchema: {
|
|
6575
|
+
type: "object",
|
|
6576
|
+
properties: {
|
|
6577
|
+
tasks: {
|
|
6578
|
+
type: "array",
|
|
6579
|
+
items: {
|
|
6580
|
+
type: "object",
|
|
6581
|
+
properties: {
|
|
6582
|
+
tool: { type: "string", description: "\u5DE5\u5177\u540D\u79F0" },
|
|
6583
|
+
args: { type: "object", description: "\u5DE5\u5177\u53C2\u6570\uFF08\u4E0D\u542B instance\uFF09" },
|
|
6584
|
+
instance: { type: "string", description: "\u76EE\u6807\u5B9E\u4F8B key" }
|
|
6585
|
+
},
|
|
6586
|
+
required: ["tool", "instance"]
|
|
6587
|
+
},
|
|
6588
|
+
description: "\u8981\u5E76\u53D1\u6267\u884C\u7684\u4EFB\u52A1\u5217\u8868"
|
|
6589
|
+
}
|
|
6590
|
+
},
|
|
6591
|
+
required: ["tasks"]
|
|
6592
|
+
}
|
|
6593
|
+
}
|
|
6594
|
+
];
|
|
6595
|
+
}
|
|
6596
|
+
});
|
|
6597
|
+
|
|
6460
6598
|
// src/tools/index.js
|
|
6599
|
+
function getToolCategory(name) {
|
|
6600
|
+
const n = name;
|
|
6601
|
+
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";
|
|
6602
|
+
if (/^(move_|copy_|rotate_|scale_|mirror_|offset_|array_|batch_)/.test(n)) return "\u4FEE\u6539";
|
|
6603
|
+
if (/^(trim_|extend_|fillet|chamfer|break_|join_|stretch)/.test(n)) return "\u7F16\u8F91";
|
|
6604
|
+
if (/^(create_layer|delete_layer|set_layer|layer_)/.test(n)) return "\u56FE\u5C42";
|
|
6605
|
+
if (/^(create_block|insert_block|explode_block|get_block|set_block|batch_get_block|batch_set_block)/.test(n)) return "\u5757";
|
|
6606
|
+
if (/^(create_dim|list_dim|set_dim|create_hatch|set_hatch)/.test(n)) return "\u6807\u6CE8\u4E0E\u586B\u5145";
|
|
6607
|
+
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";
|
|
6608
|
+
if (/^(create_viewport|set_viewport|lock_viewport|unlock_viewport|maximize_viewport)/.test(n)) return "\u89C6\u53E3";
|
|
6609
|
+
if (/^find_/.test(n)) return "\u7A7A\u95F4\u67E5\u8BE2";
|
|
6610
|
+
if (/^(select_|get_entity|set_entity|delete_entity|get_bounding_box)/.test(n)) return "\u9009\u62E9\u4E0E\u5C5E\u6027";
|
|
6611
|
+
if (/^(open_dwg|save_dwg|export_|import_|close_dwg|publish_)/.test(n)) return "\u6587\u4EF6";
|
|
6612
|
+
if (/^(plot_|save_pdf|batch_plot|publish_layouts)/.test(n)) return "\u6253\u5370";
|
|
6613
|
+
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";
|
|
6614
|
+
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";
|
|
6615
|
+
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";
|
|
6616
|
+
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";
|
|
6617
|
+
if (/^(purge_|drawing_audit|drawing_recover|overkill)/.test(n)) return "\u6E05\u7406";
|
|
6618
|
+
if (/^(find_text|replace_text|set_text_|justify_|convert_text|explode_text)/.test(n)) return "\u6587\u5B57";
|
|
6619
|
+
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";
|
|
6620
|
+
if (/^(list_packages|search_packages|install_package|get_function_usage|list_symbols|import_funlib)/.test(n)) return "\u5305\u4E0E\u51FD\u6570";
|
|
6621
|
+
if (/^(watch_|lisp_repl|webhook_|sandbox_|audit_|cad_pool_|external_|list_data|export_to|import_external)/.test(n)) return "\u9AD8\u7EA7";
|
|
6622
|
+
if (/^(list_prompts|get_prompt|search_tools|list_tools_by_category|get_tool_info)/.test(n)) return "\u5143\u5DE5\u5177";
|
|
6623
|
+
if (/^(agent_)/.test(n)) return "Agent\u4E0A\u4E0B\u6587";
|
|
6624
|
+
return "\u5176\u4ED6";
|
|
6625
|
+
}
|
|
6461
6626
|
function addAnnotations(tool) {
|
|
6462
6627
|
const isDeprecated = DEPRECATED_TOOLS.has(tool.name);
|
|
6463
6628
|
const isPoolTool = tool.name.startsWith("cad_pool_") || tool.name === "session_pin_instance" || tool.name === "session_unpin_instance";
|
|
@@ -6477,11 +6642,12 @@ function addAnnotations(tool) {
|
|
|
6477
6642
|
destructiveHint: tool.name.startsWith("delete_") || tool.name.startsWith("purge_") || tool.name.startsWith("boolean_") || EXTRA_DESTRUCTIVE.has(tool.name),
|
|
6478
6643
|
idempotentHint: READ_ONLY_TOOLS.has(tool.name) || IDEMPOTENT_WRITE_TOOLS.has(tool.name),
|
|
6479
6644
|
openWorldHint: OPEN_WORLD_TOOLS.has(tool.name),
|
|
6645
|
+
category: getToolCategory(tool.name),
|
|
6480
6646
|
...isDeprecated ? { deprecatedReason: "This tool has been superseded. Check documentation for alternatives." } : {}
|
|
6481
6647
|
}
|
|
6482
6648
|
};
|
|
6483
6649
|
}
|
|
6484
|
-
var READ_ONLY_TOOLS, DEPRECATED_TOOLS, EXTRA_DESTRUCTIVE, IDEMPOTENT_WRITE_TOOLS, OPEN_WORLD_TOOLS,
|
|
6650
|
+
var READ_ONLY_TOOLS, DEPRECATED_TOOLS, EXTRA_DESTRUCTIVE, IDEMPOTENT_WRITE_TOOLS, OPEN_WORLD_TOOLS, tools43, toolsByName;
|
|
6485
6651
|
var init_tools = __esm({
|
|
6486
6652
|
"src/tools/index.js"() {
|
|
6487
6653
|
init_cad_tools();
|
|
@@ -6525,6 +6691,7 @@ var init_tools = __esm({
|
|
|
6525
6691
|
init_batch_transaction_tools();
|
|
6526
6692
|
init_lint_tools();
|
|
6527
6693
|
init_debug_tools();
|
|
6694
|
+
init_concurrent_tools();
|
|
6528
6695
|
READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
6529
6696
|
"get_cad_info",
|
|
6530
6697
|
"get_platform_info",
|
|
@@ -6664,7 +6831,7 @@ var init_tools = __esm({
|
|
|
6664
6831
|
"import_page_setup",
|
|
6665
6832
|
"load_linetype"
|
|
6666
6833
|
]);
|
|
6667
|
-
|
|
6834
|
+
tools43 = [
|
|
6668
6835
|
...tools,
|
|
6669
6836
|
...tools2,
|
|
6670
6837
|
...tools3,
|
|
@@ -6705,9 +6872,10 @@ var init_tools = __esm({
|
|
|
6705
6872
|
...tools39,
|
|
6706
6873
|
...tools37,
|
|
6707
6874
|
...tools40,
|
|
6708
|
-
...tools41
|
|
6875
|
+
...tools41,
|
|
6876
|
+
...tools42
|
|
6709
6877
|
].map(addAnnotations);
|
|
6710
|
-
toolsByName = new Map(
|
|
6878
|
+
toolsByName = new Map(tools43.map((t) => [t.name, t]));
|
|
6711
6879
|
}
|
|
6712
6880
|
});
|
|
6713
6881
|
|
|
@@ -6760,7 +6928,7 @@ function parseLispList(str) {
|
|
|
6760
6928
|
});
|
|
6761
6929
|
}
|
|
6762
6930
|
function createMcpServer(handlers = {}) {
|
|
6763
|
-
const { tools:
|
|
6931
|
+
const { tools: tools44 = [], handleToolCall: handleToolCall2 = () => ({ content: [] }) } = handlers;
|
|
6764
6932
|
const server = new Server(
|
|
6765
6933
|
{ name: SERVER_NAME, version: SERVER_VERSION },
|
|
6766
6934
|
{
|
|
@@ -6783,8 +6951,8 @@ function createMcpServer(handlers = {}) {
|
|
|
6783
6951
|
const params = request.params || {};
|
|
6784
6952
|
const cursor = decodeCursor(params.cursor);
|
|
6785
6953
|
const PAGE_SIZE = 100;
|
|
6786
|
-
const page =
|
|
6787
|
-
const nextCursor = cursor + PAGE_SIZE <
|
|
6954
|
+
const page = tools44.slice(cursor, cursor + PAGE_SIZE);
|
|
6955
|
+
const nextCursor = cursor + PAGE_SIZE < tools44.length ? encodeCursor(cursor + PAGE_SIZE) : void 0;
|
|
6788
6956
|
return { tools: page, nextCursor };
|
|
6789
6957
|
});
|
|
6790
6958
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -7133,11 +7301,11 @@ function createMcpServer(handlers = {}) {
|
|
|
7133
7301
|
if (p.toLowerCase().startsWith(prefix)) values.push(p);
|
|
7134
7302
|
}
|
|
7135
7303
|
} else if (ref?.type === "tool") {
|
|
7136
|
-
for (const t of
|
|
7304
|
+
for (const t of tools44) {
|
|
7137
7305
|
if (t.name.toLowerCase().startsWith(prefix)) values.push(t.name);
|
|
7138
7306
|
}
|
|
7139
7307
|
} else if (ref?.type === "ref/parameter") {
|
|
7140
|
-
const toolDef =
|
|
7308
|
+
const toolDef = tools44.find((t) => t.name === ref.name);
|
|
7141
7309
|
if (toolDef?.inputSchema?.properties) {
|
|
7142
7310
|
const paramName = argument.name;
|
|
7143
7311
|
const paramDef = toolDef.inputSchema.properties[paramName];
|
|
@@ -10670,6 +10838,87 @@ var init_lint_handlers = __esm({
|
|
|
10670
10838
|
}
|
|
10671
10839
|
});
|
|
10672
10840
|
|
|
10841
|
+
// src/handlers/meta-handlers.js
|
|
10842
|
+
var meta_handlers_exports = {};
|
|
10843
|
+
__export(meta_handlers_exports, {
|
|
10844
|
+
get_prompt_handler: () => get_prompt_handler,
|
|
10845
|
+
get_tool_info: () => get_tool_info,
|
|
10846
|
+
list_prompts_handler: () => list_prompts_handler,
|
|
10847
|
+
list_tools_by_category: () => list_tools_by_category,
|
|
10848
|
+
search_tools: () => search_tools
|
|
10849
|
+
});
|
|
10850
|
+
async function search_tools(a) {
|
|
10851
|
+
const q = (a.query || "").toLowerCase();
|
|
10852
|
+
const results = tools43.filter((t) => t.name.toLowerCase().includes(q) || (t.description || "").toLowerCase().includes(q));
|
|
10853
|
+
const text = results.length ? `\u627E\u5230 ${results.length} \u4E2A\u5DE5\u5177:
|
|
10854
|
+
${results.map((t) => `${t.name}: ${t.description}`).join("\n")}` : `\u672A\u627E\u5230\u5305\u542B "${a.query}" \u7684\u5DE5\u5177`;
|
|
10855
|
+
return { content: [{ type: "text", text }] };
|
|
10856
|
+
}
|
|
10857
|
+
async function list_tools_by_category(a) {
|
|
10858
|
+
const categories = {};
|
|
10859
|
+
for (const t of tools43) {
|
|
10860
|
+
const cat = t.annotations?.category || "\u5176\u4ED6";
|
|
10861
|
+
if (!categories[cat]) categories[cat] = [];
|
|
10862
|
+
categories[cat].push(t.name);
|
|
10863
|
+
}
|
|
10864
|
+
if (a.category) {
|
|
10865
|
+
const names = categories[a.category];
|
|
10866
|
+
return { content: [{ type: "text", text: names ? `${a.category} (${names.length}):
|
|
10867
|
+
${names.join("\n")}` : `\u672A\u627E\u5230\u5206\u7C7B: ${a.category}` }] };
|
|
10868
|
+
}
|
|
10869
|
+
const lines = [];
|
|
10870
|
+
for (const [cat, names] of Object.entries(categories)) {
|
|
10871
|
+
lines.push(`## ${cat} (${names.length})`);
|
|
10872
|
+
}
|
|
10873
|
+
lines.push(`
|
|
10874
|
+
\u5171 ${Object.keys(categories).length} \u4E2A\u5206\u7C7B`);
|
|
10875
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
10876
|
+
}
|
|
10877
|
+
async function get_tool_info(a) {
|
|
10878
|
+
if (!a.name) return { content: [{ type: "text", text: "\u9700\u8981 name \u53C2\u6570\uFF08\u5DE5\u5177\u540D\u79F0\uFF09" }], isError: true };
|
|
10879
|
+
const tool = tools43.find((t) => t.name === a.name);
|
|
10880
|
+
if (!tool) return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5DE5\u5177: ${a.name}` }], isError: true };
|
|
10881
|
+
const ann = tool.annotations || {};
|
|
10882
|
+
const required = (tool.inputSchema?.required || []).join(", ") || "\u65E0";
|
|
10883
|
+
const props = tool.inputSchema?.properties || {};
|
|
10884
|
+
const params = Object.entries(props).map(([k, v]) => {
|
|
10885
|
+
const req = required.includes(k) ? "\u5FC5\u586B" : "\u53EF\u9009";
|
|
10886
|
+
const desc = v.description || "";
|
|
10887
|
+
return ` ${k} (${req}): ${desc}`;
|
|
10888
|
+
}).join("\n");
|
|
10889
|
+
const lines = [
|
|
10890
|
+
`## ${tool.name}`,
|
|
10891
|
+
`\u63CF\u8FF0: ${tool.description || "\u65E0"}`,
|
|
10892
|
+
`\u5206\u7C7B: ${ann.category || "\u5176\u4ED6"}`,
|
|
10893
|
+
`\u53EA\u8BFB: ${ann.readOnlyHint ? "\u662F" : "\u5426"}`,
|
|
10894
|
+
`\u7834\u574F\u6027: ${ann.destructiveHint ? "\u662F" : "\u5426"}`,
|
|
10895
|
+
`\u5E42\u7B49: ${ann.idempotentHint ? "\u662F" : "\u5426"}`,
|
|
10896
|
+
`\u5F00\u653E\u4E16\u754C: ${ann.openWorldHint ? "\u662F" : "\u5426"}`,
|
|
10897
|
+
``,
|
|
10898
|
+
`\u53C2\u6570:`,
|
|
10899
|
+
params || " \u65E0\u53C2\u6570"
|
|
10900
|
+
];
|
|
10901
|
+
if (ann.deprecatedReason) {
|
|
10902
|
+
lines.push(`
|
|
10903
|
+
\u5DF2\u5F03\u7528: ${ann.deprecatedReason}`);
|
|
10904
|
+
}
|
|
10905
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
10906
|
+
}
|
|
10907
|
+
async function list_prompts_handler() {
|
|
10908
|
+
const prompts = await listPrompts2();
|
|
10909
|
+
return { content: [{ type: "text", text: JSON.stringify(prompts) }] };
|
|
10910
|
+
}
|
|
10911
|
+
async function get_prompt_handler(a) {
|
|
10912
|
+
const prompt = await getPrompt2(a.name, a.args || {});
|
|
10913
|
+
return { content: prompt.messages.map((m) => ({ type: "text", text: m.content.text || m.content })) };
|
|
10914
|
+
}
|
|
10915
|
+
var init_meta_handlers = __esm({
|
|
10916
|
+
"src/handlers/meta-handlers.js"() {
|
|
10917
|
+
init_tools();
|
|
10918
|
+
init_prompt_handlers();
|
|
10919
|
+
}
|
|
10920
|
+
});
|
|
10921
|
+
|
|
10673
10922
|
// src/handlers/package-handlers.js
|
|
10674
10923
|
var package_handlers_exports = {};
|
|
10675
10924
|
__export(package_handlers_exports, {
|
|
@@ -10679,7 +10928,7 @@ __export(package_handlers_exports, {
|
|
|
10679
10928
|
});
|
|
10680
10929
|
async function fetchPackages() {
|
|
10681
10930
|
const now = Date.now();
|
|
10682
|
-
if (cachedPackages && cachedAt2 && now - cachedAt2 <
|
|
10931
|
+
if (cachedPackages && cachedAt2 && now - cachedAt2 < CACHE_TTL) {
|
|
10683
10932
|
return cachedPackages;
|
|
10684
10933
|
}
|
|
10685
10934
|
try {
|
|
@@ -10756,7 +11005,7 @@ async function installPackage(packageName) {
|
|
|
10756
11005
|
}
|
|
10757
11006
|
return { content: [{ type: "text", text: `\u5305 "${packageName}" \u5B89\u88C5\u547D\u4EE4\u5DF2\u53D1\u9001\uFF01` }] };
|
|
10758
11007
|
}
|
|
10759
|
-
var PACKAGES_LIST_URL, cachedPackages, cachedAt2,
|
|
11008
|
+
var PACKAGES_LIST_URL, cachedPackages, cachedAt2, CACHE_TTL;
|
|
10760
11009
|
var init_package_handlers = __esm({
|
|
10761
11010
|
"src/handlers/package-handlers.js"() {
|
|
10762
11011
|
init_logger();
|
|
@@ -10765,7 +11014,7 @@ var init_package_handlers = __esm({
|
|
|
10765
11014
|
PACKAGES_LIST_URL = process.env.PACKAGES_LIST_URL || "http://s3.atlisp.cn/packages-list?fmt=json";
|
|
10766
11015
|
cachedPackages = null;
|
|
10767
11016
|
cachedAt2 = null;
|
|
10768
|
-
|
|
11017
|
+
CACHE_TTL = 10 * 60 * 1e3;
|
|
10769
11018
|
}
|
|
10770
11019
|
});
|
|
10771
11020
|
|
|
@@ -12589,6 +12838,192 @@ var init_sheetset_handlers = __esm({
|
|
|
12589
12838
|
}
|
|
12590
12839
|
});
|
|
12591
12840
|
|
|
12841
|
+
// src/handlers/skill-handlers.js
|
|
12842
|
+
var skill_handlers_exports = {};
|
|
12843
|
+
__export(skill_handlers_exports, {
|
|
12844
|
+
skill_install: () => skill_install,
|
|
12845
|
+
skill_list_categories: () => skill_list_categories,
|
|
12846
|
+
skill_list_installed: () => skill_list_installed,
|
|
12847
|
+
skill_search: () => skill_search,
|
|
12848
|
+
skill_uninstall: () => skill_uninstall
|
|
12849
|
+
});
|
|
12850
|
+
import fs8 from "fs";
|
|
12851
|
+
import path12 from "path";
|
|
12852
|
+
import os7 from "os";
|
|
12853
|
+
function readCache() {
|
|
12854
|
+
try {
|
|
12855
|
+
if (fs8.existsSync(CACHE_PATH)) return JSON.parse(fs8.readFileSync(CACHE_PATH, "utf-8"));
|
|
12856
|
+
} catch {
|
|
12857
|
+
}
|
|
12858
|
+
return null;
|
|
12859
|
+
}
|
|
12860
|
+
function writeCache(data) {
|
|
12861
|
+
try {
|
|
12862
|
+
fs8.writeFileSync(CACHE_PATH, JSON.stringify(data, null, 2), "utf-8");
|
|
12863
|
+
} catch {
|
|
12864
|
+
}
|
|
12865
|
+
}
|
|
12866
|
+
async function fetchIndex() {
|
|
12867
|
+
let index = readCache();
|
|
12868
|
+
if (index && Date.now() - index.fetchedAt < 36e5) return index;
|
|
12869
|
+
try {
|
|
12870
|
+
const resp = await fetch(REGISTRY_URL, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
12871
|
+
if (resp.ok) {
|
|
12872
|
+
index = await resp.json();
|
|
12873
|
+
index.fetchedAt = Date.now();
|
|
12874
|
+
writeCache(index);
|
|
12875
|
+
}
|
|
12876
|
+
} catch {
|
|
12877
|
+
}
|
|
12878
|
+
return index;
|
|
12879
|
+
}
|
|
12880
|
+
async function skill_search(a) {
|
|
12881
|
+
const index = await fetchIndex();
|
|
12882
|
+
if (!index?.skills) return { content: [{ type: "text", text: "\u65E0\u6CD5\u83B7\u53D6 skill \u6CE8\u518C\u8868\u7D22\u5F15" }], isError: true };
|
|
12883
|
+
const q = (a.query || "").toLowerCase();
|
|
12884
|
+
const results = index.skills.filter(
|
|
12885
|
+
(s) => s.name.toLowerCase().includes(q) || (s.description || "").toLowerCase().includes(q) || (s.tags || []).some((t) => t.toLowerCase().includes(q))
|
|
12886
|
+
);
|
|
12887
|
+
if (!results.length) return { content: [{ type: "text", text: `\u672A\u627E\u5230\u5339\u914D "${a.query}" \u7684 skill` }] };
|
|
12888
|
+
const lines = [`\u627E\u5230 ${results.length} \u4E2A skill:
|
|
12889
|
+
`];
|
|
12890
|
+
for (const s of results) {
|
|
12891
|
+
lines.push(`**${s.name}**`);
|
|
12892
|
+
if (s.description) lines.push(` \u63CF\u8FF0: ${s.description}`);
|
|
12893
|
+
if (s.tags?.length) lines.push(` \u6807\u7B7E: ${s.tags.join(", ")}`);
|
|
12894
|
+
if (s.version) lines.push(` \u7248\u672C: ${s.version}`);
|
|
12895
|
+
lines.push("");
|
|
12896
|
+
}
|
|
12897
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
12898
|
+
}
|
|
12899
|
+
async function skill_install(a) {
|
|
12900
|
+
if (!a.name) return { content: [{ type: "text", text: "\u9700\u8981 skill \u540D\u79F0" }], isError: true };
|
|
12901
|
+
const index = await fetchIndex();
|
|
12902
|
+
if (!index?.skills) return { content: [{ type: "text", text: "\u65E0\u6CD5\u83B7\u53D6 skill \u6CE8\u518C\u8868\u7D22\u5F15" }], isError: true };
|
|
12903
|
+
const skill = index.skills.find((s) => s.name === a.name);
|
|
12904
|
+
if (!skill) return { content: [{ type: "text", text: `\u672A\u627E\u5230 skill: ${a.name}` }], isError: true };
|
|
12905
|
+
const downloadUrl = skill.download_url || skill.url;
|
|
12906
|
+
if (!downloadUrl) return { content: [{ type: "text", text: `Skill "${a.name}" \u6CA1\u6709\u4E0B\u8F7D\u5730\u5740` }], isError: true };
|
|
12907
|
+
let content;
|
|
12908
|
+
try {
|
|
12909
|
+
const resp = await fetch(downloadUrl, { headers: { "User-Agent": "atlisp-mcp" } });
|
|
12910
|
+
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
|
12911
|
+
content = await resp.text();
|
|
12912
|
+
} catch (e) {
|
|
12913
|
+
return { content: [{ type: "text", text: `\u4E0B\u8F7D\u5931\u8D25: ${e.message}` }], isError: true };
|
|
12914
|
+
}
|
|
12915
|
+
try {
|
|
12916
|
+
fs8.mkdirSync(SKILLS_DIR, { recursive: true });
|
|
12917
|
+
} catch {
|
|
12918
|
+
}
|
|
12919
|
+
const safeName = a.name.replace(/[^a-zA-Z0-9\u4e00-\u9fff_-]/g, "-").substring(0, 40);
|
|
12920
|
+
const skillFile = path12.join(SKILLS_DIR, `skill-${safeName}.md`);
|
|
12921
|
+
if (fs8.existsSync(skillFile)) {
|
|
12922
|
+
return { content: [{ type: "text", text: `Skill "${a.name}" \u5DF2\u5B89\u88C5 (${skillFile})` }], isError: true };
|
|
12923
|
+
}
|
|
12924
|
+
let finalContent = content;
|
|
12925
|
+
if (!content.match(/^---\n/)) {
|
|
12926
|
+
const tags = (skill.tags || []).join(", ");
|
|
12927
|
+
finalContent = `---
|
|
12928
|
+
name: ${a.name}
|
|
12929
|
+
description: ${skill.description || ""}
|
|
12930
|
+
tags: ${tags}
|
|
12931
|
+
---
|
|
12932
|
+
|
|
12933
|
+
${content}`;
|
|
12934
|
+
}
|
|
12935
|
+
fs8.writeFileSync(skillFile, finalContent, "utf-8");
|
|
12936
|
+
return { content: [{ type: "text", text: `${skill.name} \u5B89\u88C5\u6210\u529F
|
|
12937
|
+
\u6587\u4EF6: ${skillFile}${skill.version ? `
|
|
12938
|
+
\u7248\u672C: ${skill.version}` : ""}` }] };
|
|
12939
|
+
}
|
|
12940
|
+
async function skill_list_installed() {
|
|
12941
|
+
if (!fs8.existsSync(SKILLS_DIR)) return { content: [{ type: "text", text: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684 skill" }] };
|
|
12942
|
+
const results = [];
|
|
12943
|
+
try {
|
|
12944
|
+
const entries = fs8.readdirSync(SKILLS_DIR, { withFileTypes: true });
|
|
12945
|
+
for (const entry of entries) {
|
|
12946
|
+
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
12947
|
+
const fullPath = path12.join(SKILLS_DIR, entry.name);
|
|
12948
|
+
try {
|
|
12949
|
+
const raw = fs8.readFileSync(fullPath, "utf-8");
|
|
12950
|
+
const match = raw.match(/^---\n([\s\S]*?)\n---/);
|
|
12951
|
+
if (match) {
|
|
12952
|
+
const fm = {};
|
|
12953
|
+
for (const line of match[1].split("\n")) {
|
|
12954
|
+
const sep = line.indexOf(":");
|
|
12955
|
+
if (sep > 0) fm[line.slice(0, sep).trim()] = line.slice(sep + 1).trim();
|
|
12956
|
+
}
|
|
12957
|
+
results.push({ name: fm.name || entry.name.replace(".md", ""), description: fm.description || "", tags: fm.tags || "" });
|
|
12958
|
+
} else {
|
|
12959
|
+
results.push({ name: entry.name.replace(".md", ""), description: "", tags: "" });
|
|
12960
|
+
}
|
|
12961
|
+
} catch {
|
|
12962
|
+
}
|
|
12963
|
+
}
|
|
12964
|
+
}
|
|
12965
|
+
} catch {
|
|
12966
|
+
}
|
|
12967
|
+
if (!results.length) return { content: [{ type: "text", text: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684 skill" }] };
|
|
12968
|
+
const lines = [`\u5DF2\u5B89\u88C5 ${results.length} \u4E2A skill:
|
|
12969
|
+
`];
|
|
12970
|
+
for (const s of results) {
|
|
12971
|
+
lines.push(`**${s.name}**${s.description ? ` \u2014 ${s.description}` : ""}`);
|
|
12972
|
+
if (s.tags) lines.push(` \u6807\u7B7E: ${s.tags}`);
|
|
12973
|
+
}
|
|
12974
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
12975
|
+
}
|
|
12976
|
+
async function skill_uninstall(a) {
|
|
12977
|
+
if (!a.name) return { content: [{ type: "text", text: "\u9700\u8981 skill \u540D\u79F0" }], isError: true };
|
|
12978
|
+
if (!fs8.existsSync(SKILLS_DIR)) return { content: [{ type: "text", text: `\u672A\u5B89\u88C5 skill: ${a.name}` }], isError: true };
|
|
12979
|
+
let found = null;
|
|
12980
|
+
try {
|
|
12981
|
+
const entries = fs8.readdirSync(SKILLS_DIR, { withFileTypes: true });
|
|
12982
|
+
for (const entry of entries) {
|
|
12983
|
+
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
12984
|
+
const fullPath = path12.join(SKILLS_DIR, entry.name);
|
|
12985
|
+
try {
|
|
12986
|
+
const raw = fs8.readFileSync(fullPath, "utf-8");
|
|
12987
|
+
const match = raw.match(/^---\n([\s\S]*?)\n---/);
|
|
12988
|
+
if (match) {
|
|
12989
|
+
for (const line of match[1].split("\n")) {
|
|
12990
|
+
if (line.startsWith("name:") && line.slice(5).trim() === a.name) {
|
|
12991
|
+
found = fullPath;
|
|
12992
|
+
break;
|
|
12993
|
+
}
|
|
12994
|
+
}
|
|
12995
|
+
} else if (entry.name.replace(".md", "") === a.name) {
|
|
12996
|
+
found = fullPath;
|
|
12997
|
+
}
|
|
12998
|
+
} catch {
|
|
12999
|
+
}
|
|
13000
|
+
if (found) break;
|
|
13001
|
+
}
|
|
13002
|
+
}
|
|
13003
|
+
} catch {
|
|
13004
|
+
}
|
|
13005
|
+
if (!found) return { content: [{ type: "text", text: `\u672A\u5B89\u88C5 skill: ${a.name}` }], isError: true };
|
|
13006
|
+
fs8.unlinkSync(found);
|
|
13007
|
+
return { content: [{ type: "text", text: `${a.name} \u5DF2\u5378\u8F7D` }] };
|
|
13008
|
+
}
|
|
13009
|
+
async function skill_list_categories() {
|
|
13010
|
+
const index = await fetchIndex();
|
|
13011
|
+
if (!index?.skills) return { content: [{ type: "text", text: "\u65E0\u6CD5\u83B7\u53D6 skill \u6CE8\u518C\u8868\u7D22\u5F15" }], isError: true };
|
|
13012
|
+
const cats = /* @__PURE__ */ new Set();
|
|
13013
|
+
for (const s of index.skills) for (const t of s.tags || []) cats.add(t);
|
|
13014
|
+
const sorted = Array.from(cats).sort();
|
|
13015
|
+
return { content: [{ type: "text", text: sorted.length ? `\u6CE8\u518C\u8868\u5206\u7C7B (${sorted.length}):
|
|
13016
|
+
${sorted.join("\n")}` : "\u6682\u65E0\u5206\u7C7B" }] };
|
|
13017
|
+
}
|
|
13018
|
+
var SKILLS_DIR, REGISTRY_URL, CACHE_PATH;
|
|
13019
|
+
var init_skill_handlers = __esm({
|
|
13020
|
+
"src/handlers/skill-handlers.js"() {
|
|
13021
|
+
SKILLS_DIR = path12.join(os7.homedir(), ".atlisp", "skills");
|
|
13022
|
+
REGISTRY_URL = process.env.SKILL_REGISTRY_URL || "https://raw.githubusercontent.com/atlisp/skill-registry/main/index.json";
|
|
13023
|
+
CACHE_PATH = path12.join(os7.homedir(), ".atlisp", "skill-registry-cache.json");
|
|
13024
|
+
}
|
|
13025
|
+
});
|
|
13026
|
+
|
|
12592
13027
|
// src/handlers/spatial-handlers.js
|
|
12593
13028
|
var spatial_handlers_exports = {};
|
|
12594
13029
|
__export(spatial_handlers_exports, {
|
|
@@ -13960,13 +14395,13 @@ function lispPoint(pt) {
|
|
|
13960
14395
|
}
|
|
13961
14396
|
async function attachXref(args) {
|
|
13962
14397
|
try {
|
|
13963
|
-
const
|
|
14398
|
+
const path21 = esc3(args.path);
|
|
13964
14399
|
const point = lispPoint(args.point);
|
|
13965
14400
|
const scale = args.scale || 1;
|
|
13966
14401
|
const rotation = args.rotation || 0;
|
|
13967
14402
|
const overlay = args.overlay ? "_O" : "_A";
|
|
13968
14403
|
const result = await cad.sendCommandWithResult(
|
|
13969
|
-
`(command "_.XATTACH" "${
|
|
14404
|
+
`(command "_.XATTACH" "${path21}" "${overlay}" "${point}" "${scale}" "${rotation}") (princ)`
|
|
13970
14405
|
);
|
|
13971
14406
|
return mcpSuccess(`\u5916\u90E8\u53C2\u7167\u5DF2\u9644\u7740: ${args.path}`);
|
|
13972
14407
|
} catch (e) {
|
|
@@ -14294,6 +14729,7 @@ var init_ = __esm({
|
|
|
14294
14729
|
"./handlers/function-handlers.js": () => Promise.resolve().then(() => (init_function_handlers(), function_handlers_exports)),
|
|
14295
14730
|
"./handlers/layer-handlers.js": () => Promise.resolve().then(() => (init_layer_handlers(), layer_handlers_exports)),
|
|
14296
14731
|
"./handlers/lint-handlers.js": () => Promise.resolve().then(() => (init_lint_handlers(), lint_handlers_exports)),
|
|
14732
|
+
"./handlers/meta-handlers.js": () => Promise.resolve().then(() => (init_meta_handlers(), meta_handlers_exports)),
|
|
14297
14733
|
"./handlers/package-handlers.js": () => Promise.resolve().then(() => (init_package_handlers(), package_handlers_exports)),
|
|
14298
14734
|
"./handlers/parametric-handlers.js": () => Promise.resolve().then(() => (init_parametric_handlers(), parametric_handlers_exports)),
|
|
14299
14735
|
"./handlers/pdf-annotation-handlers.js": () => Promise.resolve().then(() => (init_pdf_annotation_handlers(), pdf_annotation_handlers_exports)),
|
|
@@ -14302,6 +14738,7 @@ var init_ = __esm({
|
|
|
14302
14738
|
"./handlers/query-print-handlers.js": () => Promise.resolve().then(() => (init_query_print_handlers(), query_print_handlers_exports)),
|
|
14303
14739
|
"./handlers/resource-handlers.js": () => Promise.resolve().then(() => (init_resource_handlers(), resource_handlers_exports)),
|
|
14304
14740
|
"./handlers/sheetset-handlers.js": () => Promise.resolve().then(() => (init_sheetset_handlers(), sheetset_handlers_exports)),
|
|
14741
|
+
"./handlers/skill-handlers.js": () => Promise.resolve().then(() => (init_skill_handlers(), skill_handlers_exports)),
|
|
14305
14742
|
"./handlers/spatial-handlers.js": () => Promise.resolve().then(() => (init_spatial_handlers(), spatial_handlers_exports)),
|
|
14306
14743
|
"./handlers/style-handlers.js": () => Promise.resolve().then(() => (init_style_handlers(), style_handlers_exports)),
|
|
14307
14744
|
"./handlers/text-handlers.js": () => Promise.resolve().then(() => (init_text_handlers(), text_handlers_exports)),
|
|
@@ -14314,8 +14751,8 @@ var init_ = __esm({
|
|
|
14314
14751
|
});
|
|
14315
14752
|
|
|
14316
14753
|
// src/handler-loader.js
|
|
14317
|
-
import
|
|
14318
|
-
import
|
|
14754
|
+
import fs9 from "fs";
|
|
14755
|
+
import path13 from "path";
|
|
14319
14756
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14320
14757
|
function toolNameToFuncName(toolName) {
|
|
14321
14758
|
if (FUNCTION_OVERRIDES[toolName]) return FUNCTION_OVERRIDES[toolName];
|
|
@@ -14365,10 +14802,10 @@ async function getHandlerModule(name) {
|
|
|
14365
14802
|
async function initHandlerModules() {
|
|
14366
14803
|
if (_handlerModulesInit) return;
|
|
14367
14804
|
_handlerModulesInit = true;
|
|
14368
|
-
const handlerDir =
|
|
14805
|
+
const handlerDir = path13.join(__dirname5, "handlers");
|
|
14369
14806
|
let names;
|
|
14370
14807
|
try {
|
|
14371
|
-
names = await
|
|
14808
|
+
names = await fs9.promises.readdir(handlerDir);
|
|
14372
14809
|
} catch {
|
|
14373
14810
|
log("Handler directory not found, using static manifest");
|
|
14374
14811
|
return;
|
|
@@ -14379,6 +14816,7 @@ async function initHandlerModules() {
|
|
|
14379
14816
|
handlerModules[name] = () => globImport_handlers_handlers_js(`./handlers/${name}-handlers.js`);
|
|
14380
14817
|
}
|
|
14381
14818
|
}
|
|
14819
|
+
watchHandlers();
|
|
14382
14820
|
}
|
|
14383
14821
|
async function getHandler(toolName) {
|
|
14384
14822
|
const resolved = await resolveHandler(toolName);
|
|
@@ -14387,12 +14825,40 @@ async function getHandler(toolName) {
|
|
|
14387
14825
|
if (!mod || typeof mod[resolved.funcName] !== "function") return null;
|
|
14388
14826
|
return mod[resolved.funcName];
|
|
14389
14827
|
}
|
|
14390
|
-
|
|
14828
|
+
function watchHandlers() {
|
|
14829
|
+
if (_watcherInitialized) return;
|
|
14830
|
+
_watcherInitialized = true;
|
|
14831
|
+
const handlerDir = path13.join(__dirname5, "handlers");
|
|
14832
|
+
let debounceTimer = null;
|
|
14833
|
+
try {
|
|
14834
|
+
if (!fs9.existsSync(handlerDir)) return;
|
|
14835
|
+
fs9.watch(handlerDir, (eventType, filename) => {
|
|
14836
|
+
if (!filename || !filename.endsWith("-handlers.js")) return;
|
|
14837
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
14838
|
+
debounceTimer = setTimeout(async () => {
|
|
14839
|
+
const name = filename.replace("-handlers.js", "");
|
|
14840
|
+
moduleCache.delete(name);
|
|
14841
|
+
resolvedCache.clear();
|
|
14842
|
+
_handlerNameMapInit = false;
|
|
14843
|
+
_handlerModulesInit = false;
|
|
14844
|
+
try {
|
|
14845
|
+
await initHandlerModules();
|
|
14846
|
+
log(`Handler hot-reloaded: ${filename}`);
|
|
14847
|
+
} catch (e) {
|
|
14848
|
+
log(`Handler reload failed for ${filename}: ${e.message}`);
|
|
14849
|
+
}
|
|
14850
|
+
}, 300);
|
|
14851
|
+
});
|
|
14852
|
+
} catch (e) {
|
|
14853
|
+
log(`Handler watch error: ${e.message}`);
|
|
14854
|
+
}
|
|
14855
|
+
}
|
|
14856
|
+
var __dirname5, _handlerModulesInit, _handlerNameMapInit, handlerModules, moduleCache, resolvedCache, FUNCTION_OVERRIDES, _watcherInitialized;
|
|
14391
14857
|
var init_handler_loader = __esm({
|
|
14392
14858
|
"src/handler-loader.js"() {
|
|
14393
14859
|
init_logger();
|
|
14394
14860
|
init_();
|
|
14395
|
-
__dirname5 =
|
|
14861
|
+
__dirname5 = path13.dirname(fileURLToPath5(import.meta.url));
|
|
14396
14862
|
_handlerModulesInit = false;
|
|
14397
14863
|
_handlerNameMapInit = false;
|
|
14398
14864
|
handlerModules = {};
|
|
@@ -14404,16 +14870,18 @@ var init_handler_loader = __esm({
|
|
|
14404
14870
|
get_dimension: "getDimensionValue",
|
|
14405
14871
|
eval_lisp_with_result: "evalLisp"
|
|
14406
14872
|
};
|
|
14873
|
+
_watcherInitialized = false;
|
|
14407
14874
|
}
|
|
14408
14875
|
});
|
|
14409
14876
|
|
|
14410
14877
|
// src/streaming.js
|
|
14411
|
-
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14416
|
-
const ssgetExpr =
|
|
14878
|
+
function escapeLispStr(str) {
|
|
14879
|
+
if (typeof str !== "string") return "";
|
|
14880
|
+
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
14881
|
+
}
|
|
14882
|
+
async function streamEntities({ filterExpr, extractFields, itemMapper, offset, limit, hasFilter, warnThreshold, overLimitMsg, resultProp }) {
|
|
14883
|
+
const ssgetExpr = filterExpr ? `(ssget "_X" ${filterExpr})` : `(ssget "_X")`;
|
|
14884
|
+
const extractCode = extractFields.length === 1 ? `(list ${extractFields.join(" ")})` : `(list ${extractFields.join(" ")})`;
|
|
14417
14885
|
const lisp = `(progn
|
|
14418
14886
|
(setq ss ${ssgetExpr})
|
|
14419
14887
|
(setq total (if ss (sslength ss) 0))
|
|
@@ -14425,10 +14893,10 @@ async function streamEntitiesByType({ type = null, layer = null, chunk = STREAM_
|
|
|
14425
14893
|
(setq result (list total))
|
|
14426
14894
|
(setq i ${offset})
|
|
14427
14895
|
(setq count 0)
|
|
14428
|
-
(while (and (< i total) (< count ${
|
|
14896
|
+
(while (and (< i total) (< count ${limit}))
|
|
14429
14897
|
(setq e (ssname ss i))
|
|
14430
14898
|
(setq elist (entget e))
|
|
14431
|
-
(setq result (cons
|
|
14899
|
+
(setq result (cons ${extractCode} result))
|
|
14432
14900
|
(setq i (1+ i))
|
|
14433
14901
|
(setq count (1+ count)))
|
|
14434
14902
|
(reverse result)))))`;
|
|
@@ -14442,108 +14910,68 @@ async function streamEntitiesByType({ type = null, layer = null, chunk = STREAM_
|
|
|
14442
14910
|
offset: 0,
|
|
14443
14911
|
count: 0,
|
|
14444
14912
|
hasMore: false,
|
|
14445
|
-
|
|
14446
|
-
error: `\u5B9E\u4F53\u6570\u91CF (${parsed[1]}) \u8D85\u8FC7\u6700\u5927\u9650\u5236 (${MAX_ENTITY_LIMIT})\uFF0C
|
|
14913
|
+
[resultProp]: [],
|
|
14914
|
+
error: `\u5B9E\u4F53\u6570\u91CF (${parsed[1]}) \u8D85\u8FC7\u6700\u5927\u9650\u5236 (${MAX_ENTITY_LIMIT})\uFF0C${overLimitMsg}`
|
|
14447
14915
|
};
|
|
14448
14916
|
}
|
|
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`;
|
|
14917
|
+
const items = parsed.slice(1).map(itemMapper);
|
|
14918
|
+
const result = { total, offset, count: items.length, hasMore: offset + items.length < total, [resultProp]: items };
|
|
14919
|
+
if (!hasFilter && total > warnThreshold) {
|
|
14920
|
+
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
14921
|
}
|
|
14460
14922
|
return result;
|
|
14461
14923
|
} catch {
|
|
14462
|
-
return { total: 0, offset: 0, count: 0, hasMore: false,
|
|
14924
|
+
return { total: 0, offset: 0, count: 0, hasMore: false, [resultProp]: [] };
|
|
14463
14925
|
}
|
|
14464
14926
|
}
|
|
14927
|
+
async function streamEntitiesByType({ type = null, layer = null, chunk = STREAM_CHUNK_SIZE, offset = 0 }) {
|
|
14928
|
+
const filters = [];
|
|
14929
|
+
if (type) filters.push(`(cons 0 "${escapeLispStr(type)}")`);
|
|
14930
|
+
if (layer) filters.push(`(cons 8 "${escapeLispStr(layer)}")`);
|
|
14931
|
+
const filterExpr = filters.length > 0 ? `(list ${filters.join(" ")})` : null;
|
|
14932
|
+
return streamEntities({
|
|
14933
|
+
filterExpr,
|
|
14934
|
+
extractFields: ["(list (cdr (assoc 0 elist)) (cdr (assoc 5 elist)) (cdr (assoc 8 elist)))"],
|
|
14935
|
+
itemMapper: (item) => ({ type: item[0], handle: item[1], layer: item[2] }),
|
|
14936
|
+
offset,
|
|
14937
|
+
limit: chunk,
|
|
14938
|
+
hasFilter: !!(type || layer),
|
|
14939
|
+
warnThreshold: UNFILTERED_WARN_THRESHOLD,
|
|
14940
|
+
overLimitMsg: "\u8BF7\u4F7F\u7528 type/layer \u8FC7\u6EE4",
|
|
14941
|
+
resultProp: "entities"
|
|
14942
|
+
});
|
|
14943
|
+
}
|
|
14465
14944
|
async function streamTextContent({ layer = null, bbox = null, offset = 0, limit = 100 }) {
|
|
14466
14945
|
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
|
-
}
|
|
14946
|
+
if (layer) textFilters.push(`(cons 8 "${escapeLispStr(layer)}")`);
|
|
14947
|
+
const filterExpr = `(list '(-4 . "<OR") ${textFilters.join(" ")} '(-4 . "OR>"))`;
|
|
14948
|
+
return streamEntities({
|
|
14949
|
+
filterExpr,
|
|
14950
|
+
extractFields: ["(list (cdr (assoc 5 elist)) (cdr (assoc 1 elist)) (cdr (assoc 10 elist)))"],
|
|
14951
|
+
itemMapper: (item) => ({ handle: item[0], text: item[1], point: item[2] }),
|
|
14952
|
+
offset,
|
|
14953
|
+
limit,
|
|
14954
|
+
hasFilter: !!layer,
|
|
14955
|
+
warnThreshold: UNFILTERED_WARN_THRESHOLD,
|
|
14956
|
+
overLimitMsg: "\u8BF7\u4F7F\u7528 layer \u8FC7\u6EE4",
|
|
14957
|
+
resultProp: "texts"
|
|
14958
|
+
});
|
|
14506
14959
|
}
|
|
14507
14960
|
async function streamBlockRefs({ blockName = null, offset = 0, limit = 100 }) {
|
|
14508
14961
|
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
|
-
}
|
|
14962
|
+
if (blockName) filters.push(`(cons 2 "${escapeLispStr(blockName)}")`);
|
|
14963
|
+
const filterExpr = filters.length > 0 ? `(list ${filters.join(" ")})` : null;
|
|
14964
|
+
return streamEntities({
|
|
14965
|
+
filterExpr,
|
|
14966
|
+
extractFields: ["(list (cdr (assoc 2 elist)) (cdr (assoc 5 elist)) (cdr (assoc 10 elist)))"],
|
|
14967
|
+
itemMapper: (item) => ({ blockName: item[0], handle: item[1], insertionPoint: item[2] }),
|
|
14968
|
+
offset,
|
|
14969
|
+
limit,
|
|
14970
|
+
hasFilter: !!blockName,
|
|
14971
|
+
warnThreshold: UNFILTERED_WARN_THRESHOLD,
|
|
14972
|
+
overLimitMsg: "\u8BF7\u4F7F\u7528 blockName \u8FC7\u6EE4",
|
|
14973
|
+
resultProp: "refs"
|
|
14974
|
+
});
|
|
14547
14975
|
}
|
|
14548
14976
|
var STREAM_CHUNK_SIZE, MAX_ENTITY_LIMIT, UNFILTERED_WARN_THRESHOLD;
|
|
14549
14977
|
var init_streaming = __esm({
|
|
@@ -14555,6 +14983,74 @@ var init_streaming = __esm({
|
|
|
14555
14983
|
}
|
|
14556
14984
|
});
|
|
14557
14985
|
|
|
14986
|
+
// src/cad-rot-helper.js
|
|
14987
|
+
import edge from "edge-js";
|
|
14988
|
+
import path14 from "path";
|
|
14989
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
14990
|
+
function getRotHelper() {
|
|
14991
|
+
if (_rotHelper) return _rotHelper;
|
|
14992
|
+
const dllPath = path14.join(projectRoot, "dist", "cad-rothelper.dll");
|
|
14993
|
+
try {
|
|
14994
|
+
_rotHelper = edge.func({
|
|
14995
|
+
assemblyFile: dllPath,
|
|
14996
|
+
typeName: "CadRotHelper.RotEnumerator",
|
|
14997
|
+
methodName: "EnumerateAll"
|
|
14998
|
+
});
|
|
14999
|
+
return _rotHelper;
|
|
15000
|
+
} catch (e) {
|
|
15001
|
+
error(`ROT \u5E2E\u52A9\u5668\u52A0\u8F7D\u5931\u8D25: ${e.message}`);
|
|
15002
|
+
return null;
|
|
15003
|
+
}
|
|
15004
|
+
}
|
|
15005
|
+
async function discoverCadInstances() {
|
|
15006
|
+
const helper = getRotHelper();
|
|
15007
|
+
if (!helper) {
|
|
15008
|
+
log("ROT \u5E2E\u52A9\u5668\u4E0D\u53EF\u7528\uFF0C\u8DF3\u8FC7 CAD \u5B9E\u4F8B\u53D1\u73B0");
|
|
15009
|
+
return [];
|
|
15010
|
+
}
|
|
15011
|
+
return new Promise((resolve) => {
|
|
15012
|
+
helper(null, (err, result) => {
|
|
15013
|
+
if (err) {
|
|
15014
|
+
error(`ROT \u679A\u4E3E\u5931\u8D25: ${err.message}`);
|
|
15015
|
+
resolve([]);
|
|
15016
|
+
return;
|
|
15017
|
+
}
|
|
15018
|
+
if (!Array.isArray(result)) {
|
|
15019
|
+
resolve([]);
|
|
15020
|
+
return;
|
|
15021
|
+
}
|
|
15022
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15023
|
+
const instances = [];
|
|
15024
|
+
for (const entry of result) {
|
|
15025
|
+
if (!entry.appName) continue;
|
|
15026
|
+
const pidKey = `${entry.appName}-${entry.pid}`;
|
|
15027
|
+
if (seen.has(pidKey)) continue;
|
|
15028
|
+
seen.add(pidKey);
|
|
15029
|
+
const key = `${entry.appName.toLowerCase()}-${entry.pid}`;
|
|
15030
|
+
instances.push({
|
|
15031
|
+
key,
|
|
15032
|
+
platform: entry.appName,
|
|
15033
|
+
pid: entry.pid,
|
|
15034
|
+
hwnd: entry.hwnd,
|
|
15035
|
+
version: entry.version,
|
|
15036
|
+
moniker: entry.name
|
|
15037
|
+
});
|
|
15038
|
+
}
|
|
15039
|
+
log(`ROT \u53D1\u73B0: ${instances.length} \u4E2A CAD \u5B9E\u4F8B (${instances.map((i) => `${i.platform}#${i.pid}`).join(", ")})`);
|
|
15040
|
+
resolve(instances);
|
|
15041
|
+
});
|
|
15042
|
+
});
|
|
15043
|
+
}
|
|
15044
|
+
var __filename, projectRoot, _rotHelper;
|
|
15045
|
+
var init_cad_rot_helper = __esm({
|
|
15046
|
+
"src/cad-rot-helper.js"() {
|
|
15047
|
+
init_logger();
|
|
15048
|
+
__filename = fileURLToPath6(import.meta.url);
|
|
15049
|
+
projectRoot = path14.dirname(path14.dirname(__filename));
|
|
15050
|
+
_rotHelper = null;
|
|
15051
|
+
}
|
|
15052
|
+
});
|
|
15053
|
+
|
|
14558
15054
|
// src/cad-pool.js
|
|
14559
15055
|
var POOL_STRATEGIES, CadConnectionPool, pool;
|
|
14560
15056
|
var init_cad_pool = __esm({
|
|
@@ -14562,6 +15058,8 @@ var init_cad_pool = __esm({
|
|
|
14562
15058
|
init_cad();
|
|
14563
15059
|
init_logger();
|
|
14564
15060
|
init_config();
|
|
15061
|
+
init_cad_rot_helper();
|
|
15062
|
+
init_resource_cache();
|
|
14565
15063
|
POOL_STRATEGIES = {
|
|
14566
15064
|
ROUND_ROBIN: "round-robin",
|
|
14567
15065
|
LEAST_BUSY: "least-busy",
|
|
@@ -14570,9 +15068,8 @@ var init_cad_pool = __esm({
|
|
|
14570
15068
|
CadConnectionPool = class {
|
|
14571
15069
|
_instances = /* @__PURE__ */ new Map();
|
|
14572
15070
|
_maxPoolSize = 3;
|
|
14573
|
-
_activeKey =
|
|
15071
|
+
_activeKey = null;
|
|
14574
15072
|
_strategy = POOL_STRATEGIES.MANUAL;
|
|
14575
|
-
_rrIndex = 0;
|
|
14576
15073
|
_reconnectTimers = /* @__PURE__ */ new Map();
|
|
14577
15074
|
_reconnectCounts = /* @__PURE__ */ new Map();
|
|
14578
15075
|
_maxReconnectAttempts = 10;
|
|
@@ -14582,30 +15079,8 @@ var init_cad_pool = __esm({
|
|
|
14582
15079
|
this._maxPoolSize = config_default.maxPoolSize || 3;
|
|
14583
15080
|
}
|
|
14584
15081
|
getConnection(key) {
|
|
14585
|
-
this._ensureDefault();
|
|
14586
15082
|
return this._instances.get(key)?.connection || null;
|
|
14587
15083
|
}
|
|
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
15084
|
/**
|
|
14610
15085
|
* Connect to a CAD instance and add it to the pool.
|
|
14611
15086
|
* @param {string} key - Instance identifier
|
|
@@ -14613,14 +15088,30 @@ var init_cad_pool = __esm({
|
|
|
14613
15088
|
* @param {object} [options] - Additional options
|
|
14614
15089
|
* @param {string} [options.label] - Human-readable label
|
|
14615
15090
|
* @param {boolean} [options.autoReconnect=true] - Auto-reconnect on failure
|
|
15091
|
+
* @param {number} [options.pid] - Target process PID (find via ROT)
|
|
14616
15092
|
* @param {boolean} [options.makeActive=true] - Set as active after connecting
|
|
14617
15093
|
*/
|
|
14618
15094
|
async connect(key = "default", platform = null, options = {}) {
|
|
14619
|
-
|
|
14620
|
-
const { label, autoReconnect = true, makeActive = true } = options || {};
|
|
15095
|
+
const { label, autoReconnect = true, makeActive = true, pid } = options || {};
|
|
14621
15096
|
if (this._instances.size >= this._maxPoolSize && !this._instances.has(key)) {
|
|
14622
15097
|
throw new Error(`\u8FDE\u63A5\u6C60\u5DF2\u6EE1 (${this._maxPoolSize})\uFF0C\u65E0\u6CD5\u6DFB\u52A0\u65B0\u5B9E\u4F8B "${key}"`);
|
|
14623
15098
|
}
|
|
15099
|
+
if (pid != null) {
|
|
15100
|
+
const instances = await discoverCadInstances();
|
|
15101
|
+
const match = instances.find((i) => i.pid === pid);
|
|
15102
|
+
if (!match) {
|
|
15103
|
+
error(`\u8FDE\u63A5\u6C60: \u672A\u627E\u5230 PID ${pid} \u7684 CAD \u5B9E\u4F8B`);
|
|
15104
|
+
return false;
|
|
15105
|
+
}
|
|
15106
|
+
platform = platform || match.platform;
|
|
15107
|
+
if (key === "default" || key === pid.toString()) {
|
|
15108
|
+
key = match.key;
|
|
15109
|
+
}
|
|
15110
|
+
if (match.moniker) {
|
|
15111
|
+
if (!options) options = {};
|
|
15112
|
+
options._moniker = match.moniker;
|
|
15113
|
+
}
|
|
15114
|
+
}
|
|
14624
15115
|
let entry = this._instances.get(key);
|
|
14625
15116
|
if (entry && entry.connected) {
|
|
14626
15117
|
return true;
|
|
@@ -14642,7 +15133,9 @@ var init_cad_pool = __esm({
|
|
|
14642
15133
|
}
|
|
14643
15134
|
const conn = entry.connection;
|
|
14644
15135
|
try {
|
|
14645
|
-
const
|
|
15136
|
+
const moniker = options._moniker || entry.moniker;
|
|
15137
|
+
const connectOpts = moniker ? { moniker, key } : {};
|
|
15138
|
+
const ok = await conn.connect(platform, connectOpts);
|
|
14646
15139
|
if (ok) {
|
|
14647
15140
|
entry.connected = true;
|
|
14648
15141
|
entry.platform = conn.getPlatform();
|
|
@@ -14666,17 +15159,6 @@ var init_cad_pool = __esm({
|
|
|
14666
15159
|
* Disconnect and remove an instance from the pool.
|
|
14667
15160
|
*/
|
|
14668
15161
|
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
15162
|
const entry = this._instances.get(key);
|
|
14681
15163
|
if (!entry) return false;
|
|
14682
15164
|
this._clearReconnectTimer(key);
|
|
@@ -14687,7 +15169,12 @@ var init_cad_pool = __esm({
|
|
|
14687
15169
|
}
|
|
14688
15170
|
this._instances.delete(key);
|
|
14689
15171
|
if (this._activeKey === key) {
|
|
14690
|
-
this.
|
|
15172
|
+
const remaining = Array.from(this._instances.keys());
|
|
15173
|
+
if (remaining.length > 0) {
|
|
15174
|
+
this.setActive(remaining[0]);
|
|
15175
|
+
} else {
|
|
15176
|
+
this._activeKey = null;
|
|
15177
|
+
}
|
|
14691
15178
|
}
|
|
14692
15179
|
log(`\u8FDE\u63A5\u6C60: \u5B9E\u4F8B "${key}" \u5DF2\u65AD\u5F00\u5E76\u79FB\u9664`);
|
|
14693
15180
|
return true;
|
|
@@ -14696,7 +15183,6 @@ var init_cad_pool = __esm({
|
|
|
14696
15183
|
* Set the active instance. All cad.* calls will be routed here.
|
|
14697
15184
|
*/
|
|
14698
15185
|
setActive(key) {
|
|
14699
|
-
this._ensureDefault();
|
|
14700
15186
|
const entry = this._instances.get(key);
|
|
14701
15187
|
if (!entry) {
|
|
14702
15188
|
error(`\u8FDE\u63A5\u6C60: \u5B9E\u4F8B "${key}" \u4E0D\u5B58\u5728`);
|
|
@@ -14704,47 +15190,88 @@ var init_cad_pool = __esm({
|
|
|
14704
15190
|
}
|
|
14705
15191
|
this._activeKey = key;
|
|
14706
15192
|
setActiveConnection(entry.connection);
|
|
15193
|
+
setInstanceKey(key);
|
|
14707
15194
|
cad.connected = entry.connected;
|
|
14708
15195
|
log(`\u8FDE\u63A5\u6C60: \u5DF2\u5207\u6362\u5230\u5B9E\u4F8B "${key}"`);
|
|
15196
|
+
if (this._onInstanceSwitch) {
|
|
15197
|
+
try {
|
|
15198
|
+
this._onInstanceSwitch(key, entry);
|
|
15199
|
+
} catch (e) {
|
|
15200
|
+
error(`\u5207\u6362\u56DE\u8C03\u7528\u9519\u8BEF: ${e.message}`);
|
|
15201
|
+
}
|
|
15202
|
+
}
|
|
14709
15203
|
return true;
|
|
14710
15204
|
}
|
|
15205
|
+
/**
|
|
15206
|
+
* Register a callback invoked after every instance switch.
|
|
15207
|
+
* @param {function} fn - (key, entry) => void
|
|
15208
|
+
*/
|
|
15209
|
+
onInstanceSwitch(fn) {
|
|
15210
|
+
this._onInstanceSwitch = fn;
|
|
15211
|
+
}
|
|
14711
15212
|
/**
|
|
14712
15213
|
* Discover and add all running CAD instances.
|
|
14713
|
-
*
|
|
15214
|
+
* Uses ROT enumeration to find all instances (including multiple of the same platform).
|
|
15215
|
+
* Falls back to GetActiveObject per platform when ROT is unavailable.
|
|
14714
15216
|
*/
|
|
14715
15217
|
async discover() {
|
|
14716
|
-
|
|
14717
|
-
const
|
|
14718
|
-
|
|
14719
|
-
for (const
|
|
14720
|
-
const key =
|
|
15218
|
+
const resultEntries = [];
|
|
15219
|
+
const rotInstances = await discoverCadInstances();
|
|
15220
|
+
const rotHadResults = rotInstances.length > 0;
|
|
15221
|
+
for (const inst of rotInstances) {
|
|
15222
|
+
const key = inst.key;
|
|
14721
15223
|
if (this._instances.has(key) && this._instances.get(key).connected) {
|
|
14722
|
-
|
|
15224
|
+
resultEntries.push(this._instances.get(key));
|
|
14723
15225
|
continue;
|
|
14724
15226
|
}
|
|
14725
|
-
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14730
|
-
|
|
14731
|
-
|
|
14732
|
-
|
|
14733
|
-
|
|
14734
|
-
|
|
14735
|
-
|
|
14736
|
-
|
|
14737
|
-
|
|
14738
|
-
|
|
14739
|
-
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
|
|
15227
|
+
this._instances.set(key, {
|
|
15228
|
+
key,
|
|
15229
|
+
connection: null,
|
|
15230
|
+
platform: inst.platform,
|
|
15231
|
+
pid: inst.pid,
|
|
15232
|
+
version: inst.version,
|
|
15233
|
+
moniker: inst.moniker,
|
|
15234
|
+
connected: false,
|
|
15235
|
+
lastPing: Date.now(),
|
|
15236
|
+
createdAt: Date.now(),
|
|
15237
|
+
label: `${inst.platform} #${inst.pid} ${inst.version || ""}`.trim(),
|
|
15238
|
+
autoReconnect: false
|
|
15239
|
+
});
|
|
15240
|
+
log(`\u8FDE\u63A5\u6C60: \u53D1\u73B0 ${inst.platform} \u5B9E\u4F8B PID=${inst.pid}`);
|
|
15241
|
+
resultEntries.push(this._instances.get(key));
|
|
15242
|
+
}
|
|
15243
|
+
if (!rotHadResults) {
|
|
15244
|
+
const connectWithTimeout = (conn, platform, ms = 4e3) => Promise.race([
|
|
15245
|
+
conn.connect(platform),
|
|
15246
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), ms))
|
|
15247
|
+
]);
|
|
15248
|
+
for (const platform of ["AutoCAD", "ZWCAD", "GStarCAD", "BricsCAD"]) {
|
|
15249
|
+
const key = platform.toLowerCase();
|
|
15250
|
+
if (this._instances.has(key) && this._instances.get(key).connected) continue;
|
|
15251
|
+
try {
|
|
15252
|
+
const tempConn = createCadConnection();
|
|
15253
|
+
const ok = await connectWithTimeout(tempConn, platform);
|
|
15254
|
+
if (ok) {
|
|
15255
|
+
const label = `${platform} ${tempConn.getVersion() || ""}`.trim();
|
|
15256
|
+
this._instances.set(key, {
|
|
15257
|
+
key,
|
|
15258
|
+
connection: tempConn,
|
|
15259
|
+
platform: tempConn.getPlatform(),
|
|
15260
|
+
version: tempConn.getVersion(),
|
|
15261
|
+
connected: true,
|
|
15262
|
+
lastPing: Date.now(),
|
|
15263
|
+
createdAt: Date.now(),
|
|
15264
|
+
label,
|
|
15265
|
+
autoReconnect: true
|
|
15266
|
+
});
|
|
15267
|
+
log(`\u8FDE\u63A5\u6C60: \u53D1\u73B0 ${label}`);
|
|
15268
|
+
resultEntries.push(this._instances.get(key));
|
|
15269
|
+
}
|
|
15270
|
+
} catch (e) {
|
|
14743
15271
|
}
|
|
14744
|
-
} catch (e) {
|
|
14745
15272
|
}
|
|
14746
15273
|
}
|
|
14747
|
-
return
|
|
15274
|
+
return resultEntries.map((e) => ({
|
|
14748
15275
|
key: e.key,
|
|
14749
15276
|
connected: e.connected,
|
|
14750
15277
|
platform: e.platform,
|
|
@@ -14757,7 +15284,6 @@ var init_cad_pool = __esm({
|
|
|
14757
15284
|
* Health check for all instances.
|
|
14758
15285
|
*/
|
|
14759
15286
|
async healthCheck() {
|
|
14760
|
-
this._ensureDefault();
|
|
14761
15287
|
const results = [];
|
|
14762
15288
|
for (const [key, entry] of this._instances) {
|
|
14763
15289
|
try {
|
|
@@ -14803,14 +15329,21 @@ var init_cad_pool = __esm({
|
|
|
14803
15329
|
* Get the active instance.
|
|
14804
15330
|
*/
|
|
14805
15331
|
getActive() {
|
|
14806
|
-
this._ensureDefault();
|
|
14807
15332
|
return this._instances.get(this._activeKey) || null;
|
|
14808
15333
|
}
|
|
14809
15334
|
/**
|
|
14810
15335
|
* Get stats for all instances.
|
|
14811
15336
|
*/
|
|
14812
15337
|
getStats() {
|
|
14813
|
-
this.
|
|
15338
|
+
if (this._instances.size === 0) {
|
|
15339
|
+
return {
|
|
15340
|
+
total: 0,
|
|
15341
|
+
maxPoolSize: this._maxPoolSize,
|
|
15342
|
+
active: null,
|
|
15343
|
+
strategy: this._strategy,
|
|
15344
|
+
instances: []
|
|
15345
|
+
};
|
|
15346
|
+
}
|
|
14814
15347
|
return {
|
|
14815
15348
|
total: this._instances.size,
|
|
14816
15349
|
maxPoolSize: this._maxPoolSize,
|
|
@@ -14822,7 +15355,7 @@ var init_cad_pool = __esm({
|
|
|
14822
15355
|
platform: i.platform,
|
|
14823
15356
|
version: i.version,
|
|
14824
15357
|
label: i.label,
|
|
14825
|
-
queueSize: i.connection
|
|
15358
|
+
queueSize: i.connection?._getQueueSize ? i.connection._getQueueSize() : 0,
|
|
14826
15359
|
lastPingAgo: Date.now() - (i.lastPing || 0),
|
|
14827
15360
|
uptime: i.connected ? Math.round((Date.now() - i.createdAt) / 1e3) : 0
|
|
14828
15361
|
}))
|
|
@@ -14832,7 +15365,7 @@ var init_cad_pool = __esm({
|
|
|
14832
15365
|
* List all instances.
|
|
14833
15366
|
*/
|
|
14834
15367
|
listInstances() {
|
|
14835
|
-
this.
|
|
15368
|
+
if (this._instances.size === 0) return [];
|
|
14836
15369
|
return Array.from(this._instances.values()).map((i) => ({
|
|
14837
15370
|
key: i.key,
|
|
14838
15371
|
connected: i.connected,
|
|
@@ -14844,7 +15377,7 @@ var init_cad_pool = __esm({
|
|
|
14844
15377
|
}));
|
|
14845
15378
|
}
|
|
14846
15379
|
/**
|
|
14847
|
-
* Disconnect all instances.
|
|
15380
|
+
* Disconnect all instances in parallel.
|
|
14848
15381
|
*/
|
|
14849
15382
|
async disconnectAll() {
|
|
14850
15383
|
this.stopHealthCheck();
|
|
@@ -14853,27 +15386,16 @@ var init_cad_pool = __esm({
|
|
|
14853
15386
|
}
|
|
14854
15387
|
this._reconnectTimers.clear();
|
|
14855
15388
|
this._reconnectCounts.clear();
|
|
14856
|
-
|
|
15389
|
+
const entries = Array.from(this._instances.entries());
|
|
15390
|
+
this._instances.clear();
|
|
15391
|
+
this._activeKey = null;
|
|
15392
|
+
await Promise.allSettled(entries.map(async ([key, entry]) => {
|
|
14857
15393
|
try {
|
|
14858
15394
|
await entry.connection.disconnect();
|
|
14859
15395
|
} catch (e) {
|
|
14860
15396
|
error(`\u8FDE\u63A5\u6C60: \u65AD\u5F00 "${key}" \u51FA\u9519: ${e.message}`);
|
|
14861
15397
|
}
|
|
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
|
-
});
|
|
15398
|
+
}));
|
|
14877
15399
|
log("\u8FDE\u63A5\u6C60: \u6240\u6709\u5B9E\u4F8B\u5DF2\u65AD\u5F00");
|
|
14878
15400
|
}
|
|
14879
15401
|
// --- Internal ---
|
|
@@ -14933,7 +15455,7 @@ var init_cad_pool = __esm({
|
|
|
14933
15455
|
});
|
|
14934
15456
|
|
|
14935
15457
|
// src/trigger-engine.js
|
|
14936
|
-
function
|
|
15458
|
+
function escapeLispStr2(v) {
|
|
14937
15459
|
if (typeof v !== "string") return v;
|
|
14938
15460
|
return v.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
14939
15461
|
}
|
|
@@ -14941,10 +15463,10 @@ function buildFilterExpr(filter) {
|
|
|
14941
15463
|
if (!filter || typeof filter !== "object") return "nil";
|
|
14942
15464
|
const parts = [];
|
|
14943
15465
|
if (filter.type) {
|
|
14944
|
-
parts.push(`(cons 0 "${
|
|
15466
|
+
parts.push(`(cons 0 "${escapeLispStr2(filter.type)}")`);
|
|
14945
15467
|
}
|
|
14946
15468
|
if (filter.layer) {
|
|
14947
|
-
parts.push(`(cons 8 "${
|
|
15469
|
+
parts.push(`(cons 8 "${escapeLispStr2(filter.layer)}")`);
|
|
14948
15470
|
}
|
|
14949
15471
|
if (parts.length === 0) return "nil";
|
|
14950
15472
|
return `(list ${parts.join(" ")})`;
|
|
@@ -14993,7 +15515,7 @@ async function evaluateWatch(watch) {
|
|
|
14993
15515
|
return { matched, data: { count } };
|
|
14994
15516
|
}
|
|
14995
15517
|
case "layer_exists": {
|
|
14996
|
-
const lName =
|
|
15518
|
+
const lName = escapeLispStr2(watch.layerName || "");
|
|
14997
15519
|
result = await cad.sendCommandWithResult(
|
|
14998
15520
|
`(progn (if (tblsearch "LAYER" "${lName}") (list 1) (list 0)))`
|
|
14999
15521
|
);
|
|
@@ -15001,7 +15523,7 @@ async function evaluateWatch(watch) {
|
|
|
15001
15523
|
return { matched: exists, data: { exists, layerName: watch.layerName } };
|
|
15002
15524
|
}
|
|
15003
15525
|
case "doc_name": {
|
|
15004
|
-
const pattern =
|
|
15526
|
+
const pattern = escapeLispStr2(watch.pattern || "*");
|
|
15005
15527
|
result = await cad.sendCommandWithResult(
|
|
15006
15528
|
`(progn (setq _dn (getvar "dwgname")) (setq _dm (if (wcmatch _dn "${pattern}") 1 0)) (list _dm _dn))`
|
|
15007
15529
|
);
|
|
@@ -15011,14 +15533,14 @@ async function evaluateWatch(watch) {
|
|
|
15011
15533
|
return { matched, data: { matched: Boolean(matched), name } };
|
|
15012
15534
|
}
|
|
15013
15535
|
case "doc_path": {
|
|
15014
|
-
const pattern =
|
|
15536
|
+
const pattern = escapeLispStr2(watch.pattern || "*");
|
|
15015
15537
|
result = await cad.sendCommandWithResult(
|
|
15016
15538
|
`(progn (setq _dp (getvar "dwgprefix")) (setq _dm (if (wcmatch _dp "${pattern}") 1 0)) (list _dm _dp))`
|
|
15017
15539
|
);
|
|
15018
15540
|
const arr = parseLispList2(result) || [];
|
|
15019
15541
|
const matched = Number(arr[0]) !== 0;
|
|
15020
|
-
const
|
|
15021
|
-
return { matched, data: { matched: Boolean(matched), path:
|
|
15542
|
+
const path21 = String(arr[1] || "");
|
|
15543
|
+
return { matched, data: { matched: Boolean(matched), path: path21 } };
|
|
15022
15544
|
}
|
|
15023
15545
|
case "entity_selected": {
|
|
15024
15546
|
result = await cad.sendCommandWithResult(
|
|
@@ -15188,53 +15710,6 @@ function stripStringsAndComments(code) {
|
|
|
15188
15710
|
const withoutStrings = code.replace(/"([^"\\]*(?:\\.[^"\\]*)*)"/g, "");
|
|
15189
15711
|
return withoutStrings.replace(/;.*$/gm, "");
|
|
15190
15712
|
}
|
|
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
15713
|
function getSessionAllowlist(sessionId) {
|
|
15239
15714
|
if (!sessionAllowlist.has(sessionId)) {
|
|
15240
15715
|
sessionAllowlist.set(sessionId, /* @__PURE__ */ new Set());
|
|
@@ -15278,12 +15753,49 @@ function validateLispCode(code, sessionId = null) {
|
|
|
15278
15753
|
summary: blocked ? `\u5B89\u5168\u9650\u5236: ${results.filter((r) => r.blocked).map((r) => r.message).join("; ")}` : "\u901A\u8FC7"
|
|
15279
15754
|
};
|
|
15280
15755
|
}
|
|
15281
|
-
var RULES2, sessionAllowlist;
|
|
15282
|
-
var
|
|
15283
|
-
"src/lisp-
|
|
15756
|
+
var THREAT_BLOCK, THREAT_WARN, THREAT_ALLOW, CVT, SECURITY_RULES, _cachedLevel, RULES2, sessionAllowlist;
|
|
15757
|
+
var init_lisp_security = __esm({
|
|
15758
|
+
"src/lisp-security.js"() {
|
|
15284
15759
|
init_logger();
|
|
15285
15760
|
init_config();
|
|
15286
|
-
|
|
15761
|
+
THREAT_BLOCK = "block";
|
|
15762
|
+
THREAT_WARN = "warn";
|
|
15763
|
+
THREAT_ALLOW = "allow";
|
|
15764
|
+
CVT = {
|
|
15765
|
+
strict: THREAT_BLOCK,
|
|
15766
|
+
standard: THREAT_WARN,
|
|
15767
|
+
relaxed: THREAT_ALLOW
|
|
15768
|
+
};
|
|
15769
|
+
SECURITY_RULES = [
|
|
15770
|
+
{ re: /\bstartapp\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 startapp \u51FD\u6570" },
|
|
15771
|
+
{ re: /\bvl-bt\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 vl-bt \u51FD\u6570" },
|
|
15772
|
+
{ re: /\bvlax-import-type-library\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u5BFC\u5165\u7C7B\u578B\u5E93" },
|
|
15773
|
+
{ re: /\bdos_command_string\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 dos_command_string" },
|
|
15774
|
+
{ re: /\beval\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 eval \u51FD\u6570" },
|
|
15775
|
+
{ 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" },
|
|
15776
|
+
{ re: /\bload\s*[(\s"]/i, baseSeverity: THREAT_BLOCK, msg: "load \u51FD\u6570\u53EF\u80FD\u52A0\u8F7D\u5916\u90E8\u4EE3\u7801" },
|
|
15777
|
+
{ 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" },
|
|
15778
|
+
{ re: /\bvl-file-copy\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6587\u4EF6\u590D\u5236" },
|
|
15779
|
+
{ re: /\bvl-file-delete\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6587\u4EF6\u5220\u9664" },
|
|
15780
|
+
{ re: /\bvl-file-rename\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6587\u4EF6\u91CD\u547D\u540D" },
|
|
15781
|
+
{ re: /\bvl-registry-write[\s\)]/i, baseSeverity: THREAT_BLOCK, msg: "vl-registry-write \u4F1A\u4FEE\u6539\u6CE8\u518C\u8868" },
|
|
15782
|
+
{ re: /\bvl-exit-with-value\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 vl-exit-with-value" },
|
|
15783
|
+
{ re: /\bvl-exit-with-error\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 vl-exit-with-error" },
|
|
15784
|
+
{ re: /\bvlax-add-cmd\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u6CE8\u518C\u65B0\u547D\u4EE4" },
|
|
15785
|
+
{ re: /\bvla-Delete\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u76F4\u63A5\u5220\u9664 vla \u5BF9\u8C61" },
|
|
15786
|
+
{ re: /\bvla-Save\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u76F4\u63A5\u4FDD\u5B58\u6587\u6863" },
|
|
15787
|
+
{ re: /\bdirectory\s*[(\s]/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u4F7F\u7528 directory \u51FD\u6570" },
|
|
15788
|
+
{ re: /\bvla-deletefile\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u5220\u9664\u6587\u4EF6" },
|
|
15789
|
+
{ re: /\bvla-copyfile\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u590D\u5236\u6587\u4EF6" },
|
|
15790
|
+
{ re: /\bvla-movefile\b/i, baseSeverity: THREAT_BLOCK, msg: "\u7981\u6B62\u79FB\u52A8\u6587\u4EF6" }
|
|
15791
|
+
];
|
|
15792
|
+
_cachedLevel = null;
|
|
15793
|
+
try {
|
|
15794
|
+
onConfigChange(() => {
|
|
15795
|
+
_cachedLevel = null;
|
|
15796
|
+
});
|
|
15797
|
+
} catch (_) {
|
|
15798
|
+
}
|
|
15287
15799
|
RULES2 = SECURITY_RULES;
|
|
15288
15800
|
sessionAllowlist = /* @__PURE__ */ new Map();
|
|
15289
15801
|
}
|
|
@@ -15404,13 +15916,13 @@ ${analysis.errors.map((e) => ` L${e.line}: [${e.rule}] ${e.message}`).join("\n"
|
|
|
15404
15916
|
});
|
|
15405
15917
|
|
|
15406
15918
|
// src/webhook-engine.js
|
|
15407
|
-
import
|
|
15408
|
-
import
|
|
15409
|
-
import
|
|
15919
|
+
import fs10 from "fs";
|
|
15920
|
+
import path15 from "path";
|
|
15921
|
+
import os8 from "os";
|
|
15410
15922
|
function loadWebhooks() {
|
|
15411
15923
|
try {
|
|
15412
|
-
if (
|
|
15413
|
-
webhooks = JSON.parse(
|
|
15924
|
+
if (fs10.existsSync(WEBHOOKS_FILE)) {
|
|
15925
|
+
webhooks = JSON.parse(fs10.readFileSync(WEBHOOKS_FILE, "utf-8"));
|
|
15414
15926
|
}
|
|
15415
15927
|
} catch (e) {
|
|
15416
15928
|
error(`Webhook load error: ${e.message}`);
|
|
@@ -15418,8 +15930,8 @@ function loadWebhooks() {
|
|
|
15418
15930
|
}
|
|
15419
15931
|
function saveWebhooks() {
|
|
15420
15932
|
try {
|
|
15421
|
-
ensureDir(
|
|
15422
|
-
|
|
15933
|
+
ensureDir(path15.dirname(WEBHOOKS_FILE));
|
|
15934
|
+
fs10.writeFileSync(WEBHOOKS_FILE, JSON.stringify(webhooks, null, 2), "utf-8");
|
|
15423
15935
|
} catch (e) {
|
|
15424
15936
|
error(`Webhook save error: ${e.message}`);
|
|
15425
15937
|
}
|
|
@@ -15476,10 +15988,10 @@ function listWebhooks() {
|
|
|
15476
15988
|
}
|
|
15477
15989
|
function getWebhookLog(id) {
|
|
15478
15990
|
const sanitized = String(id).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
15479
|
-
const logPath =
|
|
15991
|
+
const logPath = path15.join(os8.homedir(), ".atlisp", `webhook-${sanitized}.log`);
|
|
15480
15992
|
try {
|
|
15481
|
-
if (!
|
|
15482
|
-
return
|
|
15993
|
+
if (!fs10.existsSync(logPath)) return [];
|
|
15994
|
+
return fs10.readFileSync(logPath, "utf-8").split("\n").filter(Boolean).map((l) => JSON.parse(l));
|
|
15483
15995
|
} catch (e) {
|
|
15484
15996
|
error(`Webhook log read error [${sanitized}]: ${e.message}`);
|
|
15485
15997
|
return [];
|
|
@@ -15490,30 +16002,30 @@ var init_webhook_engine = __esm({
|
|
|
15490
16002
|
"src/webhook-engine.js"() {
|
|
15491
16003
|
init_logger();
|
|
15492
16004
|
init_handler_utils();
|
|
15493
|
-
WEBHOOKS_FILE =
|
|
16005
|
+
WEBHOOKS_FILE = path15.join(os8.homedir(), ".atlisp", "webhooks.json");
|
|
15494
16006
|
webhooks = [];
|
|
15495
16007
|
loadWebhooks();
|
|
15496
16008
|
}
|
|
15497
16009
|
});
|
|
15498
16010
|
|
|
15499
16011
|
// src/audit-log.js
|
|
15500
|
-
import
|
|
15501
|
-
import
|
|
15502
|
-
import
|
|
16012
|
+
import fs11 from "fs";
|
|
16013
|
+
import path16 from "path";
|
|
16014
|
+
import os9 from "os";
|
|
15503
16015
|
import zlib from "zlib";
|
|
15504
16016
|
function rotateIfNeeded() {
|
|
15505
16017
|
try {
|
|
15506
|
-
if (
|
|
16018
|
+
if (fs11.existsSync(AUDIT_FILE) && fs11.statSync(AUDIT_FILE).size > MAX_LOG_SIZE2) {
|
|
15507
16019
|
const rotated = AUDIT_FILE.replace(".log", `.${Date.now()}.log`);
|
|
15508
|
-
|
|
16020
|
+
fs11.renameSync(AUDIT_FILE, rotated);
|
|
15509
16021
|
try {
|
|
15510
|
-
const compressed = zlib.gzipSync(
|
|
15511
|
-
|
|
15512
|
-
|
|
16022
|
+
const compressed = zlib.gzipSync(fs11.readFileSync(rotated));
|
|
16023
|
+
fs11.writeFileSync(rotated + ".gz", compressed);
|
|
16024
|
+
fs11.unlinkSync(rotated);
|
|
15513
16025
|
} catch (e) {
|
|
15514
16026
|
error(`Audit log compression failed, keeping raw file: ${e.message}`);
|
|
15515
16027
|
try {
|
|
15516
|
-
|
|
16028
|
+
fs11.unlinkSync(rotated + ".gz");
|
|
15517
16029
|
} catch {
|
|
15518
16030
|
}
|
|
15519
16031
|
}
|
|
@@ -15537,15 +16049,15 @@ function writeAuditEntry(entry) {
|
|
|
15537
16049
|
user: entry.user || "",
|
|
15538
16050
|
role: entry.role || ""
|
|
15539
16051
|
}) + "\n";
|
|
15540
|
-
|
|
16052
|
+
fs11.appendFileSync(AUDIT_FILE, line, "utf-8");
|
|
15541
16053
|
} catch (e) {
|
|
15542
16054
|
error(`Audit log write error: ${e.message}`);
|
|
15543
16055
|
}
|
|
15544
16056
|
}
|
|
15545
16057
|
function queryAuditLog(filters = {}) {
|
|
15546
16058
|
try {
|
|
15547
|
-
if (!
|
|
15548
|
-
const content =
|
|
16059
|
+
if (!fs11.existsSync(AUDIT_FILE)) return { total: 0, offset: 0, count: 0, entries: [] };
|
|
16060
|
+
const content = fs11.readFileSync(AUDIT_FILE, "utf-8");
|
|
15549
16061
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
15550
16062
|
let entries = lines.map((l) => {
|
|
15551
16063
|
try {
|
|
@@ -15577,8 +16089,8 @@ function queryAuditLog(filters = {}) {
|
|
|
15577
16089
|
}
|
|
15578
16090
|
function getAuditStats() {
|
|
15579
16091
|
try {
|
|
15580
|
-
if (!
|
|
15581
|
-
const content =
|
|
16092
|
+
if (!fs11.existsSync(AUDIT_FILE)) return { totalEntries: 0, tools: {}, errors: 0 };
|
|
16093
|
+
const content = fs11.readFileSync(AUDIT_FILE, "utf-8");
|
|
15582
16094
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
15583
16095
|
const toolCounts = {};
|
|
15584
16096
|
let errors = 0;
|
|
@@ -15594,7 +16106,7 @@ function getAuditStats() {
|
|
|
15594
16106
|
totalEntries: lines.length,
|
|
15595
16107
|
tools: toolCounts,
|
|
15596
16108
|
errors,
|
|
15597
|
-
fileSize:
|
|
16109
|
+
fileSize: fs11.existsSync(AUDIT_FILE) ? fs11.statSync(AUDIT_FILE).size : 0,
|
|
15598
16110
|
filePath: AUDIT_FILE
|
|
15599
16111
|
};
|
|
15600
16112
|
} catch (e) {
|
|
@@ -15606,8 +16118,8 @@ var init_audit_log = __esm({
|
|
|
15606
16118
|
"src/audit-log.js"() {
|
|
15607
16119
|
init_logger();
|
|
15608
16120
|
init_handler_utils();
|
|
15609
|
-
AUDIT_DIR =
|
|
15610
|
-
AUDIT_FILE =
|
|
16121
|
+
AUDIT_DIR = path16.join(os9.homedir(), "@lisp", "logs");
|
|
16122
|
+
AUDIT_FILE = path16.join(AUDIT_DIR, "audit.log");
|
|
15611
16123
|
MAX_LOG_SIZE2 = 10 * 1024 * 1024;
|
|
15612
16124
|
MAX_LOG_AGE = 90 * 24 * 60 * 60 * 1e3;
|
|
15613
16125
|
}
|
|
@@ -15641,14 +16153,17 @@ var init_agent_context = __esm({
|
|
|
15641
16153
|
});
|
|
15642
16154
|
|
|
15643
16155
|
// src/tool-validators.js
|
|
15644
|
-
function
|
|
16156
|
+
function validationError(msg) {
|
|
16157
|
+
return new MCPError(ERROR_CODES.INVALID_ARGS, msg);
|
|
16158
|
+
}
|
|
16159
|
+
function validateProps(args, props, required, path21 = "") {
|
|
15645
16160
|
for (const [key, prop] of Object.entries(props)) {
|
|
15646
|
-
const fullKey =
|
|
16161
|
+
const fullKey = path21 ? `${path21}.${key}` : key;
|
|
15647
16162
|
const isOptional = !required.includes(key);
|
|
15648
16163
|
const val = args[key];
|
|
15649
16164
|
if (val === void 0 || val === null) {
|
|
15650
16165
|
if (isOptional) continue;
|
|
15651
|
-
throw
|
|
16166
|
+
throw validationError(`Missing required argument: ${fullKey}`);
|
|
15652
16167
|
}
|
|
15653
16168
|
if (prop.type === "object" && prop.properties && typeof val === "object" && !Array.isArray(val)) {
|
|
15654
16169
|
const subRequired = prop.required || [];
|
|
@@ -15663,46 +16178,46 @@ function validateProps(args, props, required, path20 = "") {
|
|
|
15663
16178
|
const actualType = typeof val;
|
|
15664
16179
|
const expectedType = prop.type || "string";
|
|
15665
16180
|
if (expectedType === "string" && actualType !== "string" && actualType !== "number") {
|
|
15666
|
-
throw
|
|
16181
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected string, got ${actualType}`);
|
|
15667
16182
|
}
|
|
15668
16183
|
if ((expectedType === "object" || expectedType === "array") && (actualType !== "object" || val === null)) {
|
|
15669
|
-
throw
|
|
16184
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected ${expectedType}, got ${actualType}`);
|
|
15670
16185
|
}
|
|
15671
16186
|
if (expectedType === "array" && !Array.isArray(val)) {
|
|
15672
|
-
throw
|
|
16187
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected array, got ${actualType}`);
|
|
15673
16188
|
}
|
|
15674
16189
|
if (expectedType === "object" && Array.isArray(val)) {
|
|
15675
|
-
throw
|
|
16190
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected object, got array`);
|
|
15676
16191
|
}
|
|
15677
16192
|
if ((expectedType === "number" || expectedType === "integer") && actualType !== "number") {
|
|
15678
16193
|
if (expectedType === "integer" && !Number.isInteger(val)) {
|
|
15679
|
-
throw
|
|
16194
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected integer, got ${actualType}`);
|
|
15680
16195
|
}
|
|
15681
16196
|
if (expectedType === "number") {
|
|
15682
|
-
throw
|
|
16197
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected number, got ${actualType}`);
|
|
15683
16198
|
}
|
|
15684
16199
|
}
|
|
15685
16200
|
if (expectedType === "boolean" && actualType !== "boolean") {
|
|
15686
|
-
throw
|
|
16201
|
+
throw validationError(`Invalid type for argument ${fullKey}: expected boolean, got ${actualType}`);
|
|
15687
16202
|
}
|
|
15688
16203
|
if (prop.enum && !prop.enum.includes(val)) {
|
|
15689
|
-
throw
|
|
16204
|
+
throw validationError(`Invalid value for argument ${fullKey}: must be one of ${prop.enum.join(", ")}`);
|
|
15690
16205
|
}
|
|
15691
16206
|
if (expectedType === "string" && typeof prop.maxLength === "number" && String(val).length > prop.maxLength) {
|
|
15692
|
-
throw
|
|
16207
|
+
throw validationError(`Argument ${fullKey} exceeds max length of ${prop.maxLength}`);
|
|
15693
16208
|
}
|
|
15694
16209
|
if ((expectedType === "number" || expectedType === "integer") && prop.minimum != null && val < prop.minimum) {
|
|
15695
|
-
throw
|
|
16210
|
+
throw validationError(`Argument ${fullKey} must be >= ${prop.minimum}`);
|
|
15696
16211
|
}
|
|
15697
16212
|
if ((expectedType === "number" || expectedType === "integer") && prop.maximum != null && val > prop.maximum) {
|
|
15698
|
-
throw
|
|
16213
|
+
throw validationError(`Argument ${fullKey} must be <= ${prop.maximum}`);
|
|
15699
16214
|
}
|
|
15700
16215
|
}
|
|
15701
16216
|
}
|
|
15702
16217
|
function validateToolArgs(name, args) {
|
|
15703
16218
|
const toolDef = toolsByName.get(name);
|
|
15704
16219
|
if (!toolDef) {
|
|
15705
|
-
throw
|
|
16220
|
+
throw validationError(`Unknown tool: ${name}`);
|
|
15706
16221
|
}
|
|
15707
16222
|
const schema = toolDef.inputSchema;
|
|
15708
16223
|
if (!schema || !schema.properties) return true;
|
|
@@ -15710,7 +16225,7 @@ function validateToolArgs(name, args) {
|
|
|
15710
16225
|
const required = schema.required || [];
|
|
15711
16226
|
for (const req of required) {
|
|
15712
16227
|
if (!(req in (args || {}))) {
|
|
15713
|
-
throw
|
|
16228
|
+
throw validationError(`Missing required argument: ${req}`);
|
|
15714
16229
|
}
|
|
15715
16230
|
}
|
|
15716
16231
|
validateProps(args || {}, props, required);
|
|
@@ -15719,6 +16234,7 @@ function validateToolArgs(name, args) {
|
|
|
15719
16234
|
var init_tool_validators = __esm({
|
|
15720
16235
|
"src/tool-validators.js"() {
|
|
15721
16236
|
init_tools();
|
|
16237
|
+
init_errors();
|
|
15722
16238
|
}
|
|
15723
16239
|
});
|
|
15724
16240
|
|
|
@@ -15829,7 +16345,7 @@ function registerTool(toolDef, handler) {
|
|
|
15829
16345
|
}
|
|
15830
16346
|
customTools.push(toolDef);
|
|
15831
16347
|
customHandlers.set(toolDef.name, handler);
|
|
15832
|
-
|
|
16348
|
+
tools43.push(toolDef);
|
|
15833
16349
|
return true;
|
|
15834
16350
|
}
|
|
15835
16351
|
function callCustomTool(name, args) {
|
|
@@ -15849,73 +16365,92 @@ var init_tool_registry = __esm({
|
|
|
15849
16365
|
});
|
|
15850
16366
|
|
|
15851
16367
|
// src/tool-executor.js
|
|
16368
|
+
function resolveConn(instance) {
|
|
16369
|
+
if (instance) return pool.getConnection(instance) || resolveCadConnection();
|
|
16370
|
+
return cad;
|
|
16371
|
+
}
|
|
16372
|
+
async function writeAuditSuccess(name, args, options) {
|
|
16373
|
+
writeAuditEntry({
|
|
16374
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16375
|
+
tool: name,
|
|
16376
|
+
args: args || {},
|
|
16377
|
+
sessionId: options.sessionId || "",
|
|
16378
|
+
result: "success"
|
|
16379
|
+
});
|
|
16380
|
+
}
|
|
16381
|
+
async function writeAuditError(name, args, options, error2) {
|
|
16382
|
+
writeAuditEntry({
|
|
16383
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16384
|
+
tool: name,
|
|
16385
|
+
args: args || {},
|
|
16386
|
+
sessionId: options.sessionId || "",
|
|
16387
|
+
result: "error",
|
|
16388
|
+
error: error2.message
|
|
16389
|
+
});
|
|
16390
|
+
}
|
|
16391
|
+
async function beginUndo(instance) {
|
|
16392
|
+
const conn = resolveConn(instance);
|
|
16393
|
+
if (conn?.connected) {
|
|
16394
|
+
try {
|
|
16395
|
+
await conn.sendCommand('(command "_.UNDO" "_BEGIN")');
|
|
16396
|
+
return true;
|
|
16397
|
+
} catch (e) {
|
|
16398
|
+
error(`UNDO_BEGIN failed: ${e.message}`);
|
|
16399
|
+
}
|
|
16400
|
+
}
|
|
16401
|
+
return false;
|
|
16402
|
+
}
|
|
16403
|
+
async function endUndo(instance) {
|
|
16404
|
+
const conn = resolveConn(instance);
|
|
16405
|
+
try {
|
|
16406
|
+
await conn.sendCommand('(command "_.UNDO" "_END")');
|
|
16407
|
+
} catch (_) {
|
|
16408
|
+
}
|
|
16409
|
+
}
|
|
15852
16410
|
async function handleToolCall(name, args, options = {}) {
|
|
15853
16411
|
const handler = TOOL_HANDLERS[name];
|
|
15854
16412
|
if (!handler) {
|
|
15855
16413
|
const customResult = callCustomTool(name, args);
|
|
15856
16414
|
if (customResult !== null) return customResult;
|
|
15857
|
-
return
|
|
16415
|
+
return mcpErrorResponse(new MCPError(ERROR_CODES.HANDLER_NOT_FOUND, `\u672A\u77E5\u5DE5\u5177: ${name}`));
|
|
15858
16416
|
}
|
|
15859
16417
|
const isReadOnly = READ_ONLY_TOOLS.has(name);
|
|
15860
16418
|
const notifyProgress = options.notifyProgress || null;
|
|
15861
16419
|
const rateCheck = checkToolRateLimit(name, isReadOnly, options.sessionId);
|
|
15862
16420
|
if (!rateCheck.allowed) {
|
|
15863
|
-
return
|
|
16421
|
+
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
16422
|
}
|
|
15865
16423
|
return progressContext.run({ notifyProgress }, async () => {
|
|
15866
16424
|
setNotifyProgress(notifyProgress);
|
|
16425
|
+
const instance = args?.instance || null;
|
|
15867
16426
|
let undoBegun = false;
|
|
15868
16427
|
try {
|
|
15869
16428
|
validateToolArgs(name, args || {});
|
|
15870
|
-
const instance = args?.instance || null;
|
|
15871
16429
|
if (instance) {
|
|
15872
16430
|
const ctx = mcpContext.getStore();
|
|
15873
16431
|
ctx._toolInstance = instance;
|
|
15874
16432
|
}
|
|
15875
16433
|
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
|
-
}
|
|
16434
|
+
undoBegun = await beginUndo(instance);
|
|
15885
16435
|
}
|
|
15886
16436
|
const np = getNotifyProgress();
|
|
15887
16437
|
if (np) np(1, 1, `\u6B63\u5728\u6267\u884C ${name}...`);
|
|
15888
16438
|
const result = await handler(args || {});
|
|
15889
16439
|
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
|
-
});
|
|
16440
|
+
await writeAuditSuccess(name, args, options);
|
|
15897
16441
|
notifyResourceChanges(name);
|
|
15898
16442
|
return result;
|
|
15899
16443
|
} catch (e) {
|
|
15900
16444
|
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 };
|
|
16445
|
+
await writeAuditError(name, args, options, e);
|
|
16446
|
+
if (e.message.startsWith("Missing required") || e.message.startsWith("Invalid type")) {
|
|
16447
|
+
return mcpErrorResponse(new MCPError(ERROR_CODES.INVALID_ARGS, e.message));
|
|
16448
|
+
}
|
|
16449
|
+
return mcpErrorResponse(e);
|
|
15910
16450
|
} finally {
|
|
15911
16451
|
const ctx = mcpContext.getStore();
|
|
15912
16452
|
if (ctx) ctx._toolInstance = null;
|
|
15913
|
-
if (undoBegun)
|
|
15914
|
-
try {
|
|
15915
|
-
await cad.sendCommand('(command "_.UNDO" "_END")');
|
|
15916
|
-
} catch (_) {
|
|
15917
|
-
}
|
|
15918
|
-
}
|
|
16453
|
+
if (undoBegun) await endUndo(instance);
|
|
15919
16454
|
}
|
|
15920
16455
|
});
|
|
15921
16456
|
}
|
|
@@ -15932,14 +16467,12 @@ var init_tool_executor = __esm({
|
|
|
15932
16467
|
init_cad();
|
|
15933
16468
|
init_cad_pool();
|
|
15934
16469
|
init_audit_log();
|
|
16470
|
+
init_errors();
|
|
15935
16471
|
init_tool_registry();
|
|
15936
16472
|
}
|
|
15937
16473
|
});
|
|
15938
16474
|
|
|
15939
16475
|
// src/mcp-tools.js
|
|
15940
|
-
import fs11 from "fs";
|
|
15941
|
-
import path15 from "path";
|
|
15942
|
-
import os9 from "os";
|
|
15943
16476
|
import { formatCode as formatCode2 } from "@atlisp/lint/dist/formatter.js";
|
|
15944
16477
|
import { lintProject as lintProject2 } from "@atlisp/lint/dist/project.js";
|
|
15945
16478
|
import { RULES as RULES3 } from "@atlisp/lint/dist/rules.js";
|
|
@@ -15956,7 +16489,6 @@ var TOOL_HANDLERS;
|
|
|
15956
16489
|
var init_mcp_tools = __esm({
|
|
15957
16490
|
"src/mcp-tools.js"() {
|
|
15958
16491
|
init_handler_loader();
|
|
15959
|
-
init_prompt_handlers();
|
|
15960
16492
|
init_streaming();
|
|
15961
16493
|
init_constants();
|
|
15962
16494
|
init_cad();
|
|
@@ -15964,13 +16496,24 @@ var init_mcp_tools = __esm({
|
|
|
15964
16496
|
init_tools();
|
|
15965
16497
|
init_mcp_server_state();
|
|
15966
16498
|
init_trigger_engine();
|
|
15967
|
-
|
|
16499
|
+
init_lisp_security();
|
|
15968
16500
|
init_lint_analyzer();
|
|
15969
16501
|
init_repl_engine();
|
|
15970
16502
|
init_webhook_engine();
|
|
15971
16503
|
init_audit_log();
|
|
15972
16504
|
init_agent_context();
|
|
16505
|
+
init_resource_handlers();
|
|
16506
|
+
init_subscription_manager();
|
|
16507
|
+
init_skill_handlers();
|
|
16508
|
+
init_meta_handlers();
|
|
15973
16509
|
init_tool_executor();
|
|
16510
|
+
pool.onInstanceSwitch(() => {
|
|
16511
|
+
for (const uri of CAD_RESOURCE_URIS) {
|
|
16512
|
+
if (isSubscribed(uri)) {
|
|
16513
|
+
notify2(uri, null);
|
|
16514
|
+
}
|
|
16515
|
+
}
|
|
16516
|
+
});
|
|
15974
16517
|
TOOL_HANDLERS = {
|
|
15975
16518
|
// === CAD Connection ===
|
|
15976
16519
|
connect_cad: lazy("connect_cad", (a) => a?.platform),
|
|
@@ -16007,14 +16550,8 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16007
16550
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
16008
16551
|
},
|
|
16009
16552
|
// === 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
|
-
},
|
|
16553
|
+
list_prompts: list_prompts_handler,
|
|
16554
|
+
get_prompt: get_prompt_handler,
|
|
16018
16555
|
// === Entity Operations ===
|
|
16019
16556
|
get_entity: lazy("get_entity", (a) => a?.handle),
|
|
16020
16557
|
set_entity: lazy("set_entity", (a) => [a?.handle, a?.property, a?.value]),
|
|
@@ -16301,6 +16838,35 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16301
16838
|
draw_ray: lazy("draw_ray", (a) => [a.point, a.direction]),
|
|
16302
16839
|
draw_leader: lazy("draw_leader", (a) => [a.points, a.annotation]),
|
|
16303
16840
|
draw_table: lazy("draw_table", (a) => [a.insertionPoint, a.rows, a.columns, a.rowHeight, a.colWidth]),
|
|
16841
|
+
// === Batch Concurrent ===
|
|
16842
|
+
batch_concurrent_tasks: async (a) => {
|
|
16843
|
+
if (!a.tasks || !Array.isArray(a.tasks) || a.tasks.length === 0) {
|
|
16844
|
+
return { content: [{ type: "text", text: "\u9700\u8981 tasks \u6570\u7EC4" }], isError: true };
|
|
16845
|
+
}
|
|
16846
|
+
if (a.tasks.length > 50) {
|
|
16847
|
+
return { content: [{ type: "text", text: "\u6700\u591A\u652F\u6301 50 \u4E2A\u5E76\u53D1\u4EFB\u52A1" }], isError: true };
|
|
16848
|
+
}
|
|
16849
|
+
const results = await Promise.allSettled(a.tasks.map(async (task, idx) => {
|
|
16850
|
+
const handler = TOOL_HANDLERS[task.tool];
|
|
16851
|
+
if (!handler) return { index: idx, tool: task.tool, instance: task.instance, ok: false, error: `\u672A\u77E5\u5DE5\u5177: ${task.tool}` };
|
|
16852
|
+
const ctx = mcpContext.getStore();
|
|
16853
|
+
const prevInstance = ctx?._toolInstance || null;
|
|
16854
|
+
if (ctx && task.instance) ctx._toolInstance = task.instance;
|
|
16855
|
+
try {
|
|
16856
|
+
const result = await handler(task.args || {});
|
|
16857
|
+
return { index: idx, tool: task.tool, instance: task.instance, ok: !result.isError, data: result.content?.[0]?.text || result };
|
|
16858
|
+
} catch (e) {
|
|
16859
|
+
return { index: idx, tool: task.tool, instance: task.instance, ok: false, error: e.message };
|
|
16860
|
+
} finally {
|
|
16861
|
+
if (ctx) ctx._toolInstance = prevInstance;
|
|
16862
|
+
}
|
|
16863
|
+
}));
|
|
16864
|
+
const output = results.map((r, idx) => {
|
|
16865
|
+
if (r.status === "fulfilled") return r.value;
|
|
16866
|
+
return { index: idx, tool: a.tasks[idx].tool, instance: a.tasks[idx].instance, ok: false, error: r.reason?.message || "Unknown error" };
|
|
16867
|
+
});
|
|
16868
|
+
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
16869
|
+
},
|
|
16304
16870
|
// === Batch Transaction ===
|
|
16305
16871
|
batch_transaction: lazy("batch_transaction"),
|
|
16306
16872
|
// === Watch / Trigger ===
|
|
@@ -16457,6 +17023,14 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16457
17023
|
},
|
|
16458
17024
|
cad_pool_switch: (a) => {
|
|
16459
17025
|
const ok = pool.setActive(a.key);
|
|
17026
|
+
if (ok) {
|
|
17027
|
+
clearCache();
|
|
17028
|
+
for (const uri of CAD_RESOURCE_URIS) {
|
|
17029
|
+
if (isSubscribed(uri)) {
|
|
17030
|
+
notify2(uri, null);
|
|
17031
|
+
}
|
|
17032
|
+
}
|
|
17033
|
+
}
|
|
16460
17034
|
return { content: [{ type: "text", text: ok ? `\u5DF2\u5207\u6362\u5230\u5B9E\u4F8B ${a.key}` : `\u5B9E\u4F8B ${a.key} \u4E0D\u5B58\u5728` }] };
|
|
16461
17035
|
},
|
|
16462
17036
|
cad_pool_health: async () => {
|
|
@@ -16468,8 +17042,9 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16468
17042
|
return { content: [{ type: "text", text: JSON.stringify(stats, null, 2) }] };
|
|
16469
17043
|
},
|
|
16470
17044
|
cad_pool_connect: async (a) => {
|
|
16471
|
-
const ok = await pool.connect(a.key, a.platform, { label: a.label, makeActive: a.makeActive !== false });
|
|
16472
|
-
|
|
17045
|
+
const ok = await pool.connect(a.key, a.platform, { label: a.label, pid: a.pid, makeActive: a.makeActive !== false });
|
|
17046
|
+
const label = a.key || (a.pid != null ? `PID ${a.pid}` : "default");
|
|
17047
|
+
return { content: [{ type: "text", text: ok ? `\u5B9E\u4F8B "${label}" \u5DF2\u8FDE\u63A5` : `\u5B9E\u4F8B "${label}" \u8FDE\u63A5\u5931\u8D25` }] };
|
|
16473
17048
|
},
|
|
16474
17049
|
cad_pool_disconnect: async (a) => {
|
|
16475
17050
|
const ok = await pool.disconnect(a.key);
|
|
@@ -16519,261 +17094,15 @@ ${CAD_PLATFORMS.join("\n")}
|
|
|
16519
17094
|
return { content: [{ type: "text", text: "\u4E0A\u4E0B\u6587\u5DF2\u6E05\u9664" }] };
|
|
16520
17095
|
},
|
|
16521
17096
|
// === 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
|
-
},
|
|
17097
|
+
search_tools,
|
|
17098
|
+
list_tools_by_category,
|
|
17099
|
+
get_tool_info,
|
|
16573
17100
|
// === 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
|
-
}
|
|
17101
|
+
skill_search,
|
|
17102
|
+
skill_install,
|
|
17103
|
+
skill_list_installed,
|
|
17104
|
+
skill_uninstall,
|
|
17105
|
+
skill_list_categories
|
|
16777
17106
|
};
|
|
16778
17107
|
}
|
|
16779
17108
|
});
|
|
@@ -16864,7 +17193,7 @@ var init_mcp_server_state = __esm({
|
|
|
16864
17193
|
progressContext = new AsyncLocalStorage();
|
|
16865
17194
|
sessionServers = /* @__PURE__ */ new Map();
|
|
16866
17195
|
sessionTransports = /* @__PURE__ */ new Map();
|
|
16867
|
-
mcpHandlers = { tools:
|
|
17196
|
+
mcpHandlers = { tools: tools43, handleToolCall };
|
|
16868
17197
|
_stdioServer = null;
|
|
16869
17198
|
_pendingResourceUpdated = /* @__PURE__ */ new Set();
|
|
16870
17199
|
_resourceUpdatedTimer = null;
|
|
@@ -16888,11 +17217,12 @@ function mcpError(text) {
|
|
|
16888
17217
|
return { content: [{ type: "text", text: String(text) }], isError: true };
|
|
16889
17218
|
}
|
|
16890
17219
|
async function ensureCadConnected() {
|
|
16891
|
-
const { cad: cad2 } = await Promise.resolve().then(() => (init_cad(), cad_exports));
|
|
16892
|
-
|
|
16893
|
-
|
|
17220
|
+
const { cad: cad2, resolveCadConnection: resolveCadConnection2 } = await Promise.resolve().then(() => (init_cad(), cad_exports));
|
|
17221
|
+
const conn = resolveCadConnection2();
|
|
17222
|
+
if (!conn.connected) {
|
|
17223
|
+
await conn.connect();
|
|
16894
17224
|
}
|
|
16895
|
-
if (!
|
|
17225
|
+
if (!conn.connected) {
|
|
16896
17226
|
throw createError(ERROR_CODES.CAD_NOT_CONNECTED);
|
|
16897
17227
|
}
|
|
16898
17228
|
}
|
|
@@ -17077,7 +17407,7 @@ __export(resource_handlers_exports, {
|
|
|
17077
17407
|
readResource: () => readResource
|
|
17078
17408
|
});
|
|
17079
17409
|
import fs13 from "fs";
|
|
17080
|
-
import
|
|
17410
|
+
import path17 from "path";
|
|
17081
17411
|
function propertyPairsToObject(pairs) {
|
|
17082
17412
|
if (!Array.isArray(pairs)) return null;
|
|
17083
17413
|
const obj = {};
|
|
@@ -17849,7 +18179,7 @@ async function getDwgList() {
|
|
|
17849
18179
|
}
|
|
17850
18180
|
}
|
|
17851
18181
|
function loadStandardsFile(filename) {
|
|
17852
|
-
const filePath =
|
|
18182
|
+
const filePath = path17.join(STANDARDS_DIR, filename);
|
|
17853
18183
|
try {
|
|
17854
18184
|
const raw = fs13.readFileSync(filePath, "utf-8");
|
|
17855
18185
|
return JSON.parse(raw);
|
|
@@ -17949,6 +18279,119 @@ async function getDwgContext() {
|
|
|
17949
18279
|
};
|
|
17950
18280
|
}
|
|
17951
18281
|
}
|
|
18282
|
+
async function getDrawingAnalysis(params = {}) {
|
|
18283
|
+
const snapshot = await getCadSnapshot();
|
|
18284
|
+
if (!snapshot || !snapshot.cadConnected) {
|
|
18285
|
+
return { connected: false, error: "CAD \u672A\u8FDE\u63A5" };
|
|
18286
|
+
}
|
|
18287
|
+
try {
|
|
18288
|
+
const detailedCode = `(progn
|
|
18289
|
+
(vl-load-com)
|
|
18290
|
+
(setq r nil)
|
|
18291
|
+
;; entity counts by type
|
|
18292
|
+
(if (setq ss (ssget "_X"))
|
|
18293
|
+
(progn
|
|
18294
|
+
(setq total (sslength ss) i 0 cnt nil)
|
|
18295
|
+
(while (< i total)
|
|
18296
|
+
(setq typ (cdr (assoc 0 (entget (ssname ss i)))))
|
|
18297
|
+
(setq cnt (if (assoc typ cnt) (subst (cons typ (1+ (cdr (assoc typ cnt)))) (assoc typ cnt) cnt) (cons (cons typ 1) cnt)))
|
|
18298
|
+
(setq i (1+ i)))
|
|
18299
|
+
(setq r (cons (cons "entityCount" total) r))
|
|
18300
|
+
(setq r (cons (cons "entityByType" cnt) r)))
|
|
18301
|
+
(setq r (cons (cons "entityCount" 0) r)))
|
|
18302
|
+
;; block usage
|
|
18303
|
+
(setq blocks nil)
|
|
18304
|
+
(vlax-for b (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
|
|
18305
|
+
(if (and (= (vla-get-IsXref b) :vlax-false) (/= (vla-get-Name b) "*Model_Space") (/= (vla-get-Name b) "*Paper_Space"))
|
|
18306
|
+
(setq blocks (cons (list "name" (vla-get-Name b) "count" (vla-get-Count b) "isDynamic" (vla-get-IsDynamicBlock b)) blocks))))
|
|
18307
|
+
(setq r (cons (cons "blockUsage" blocks) r))
|
|
18308
|
+
;; layer summary
|
|
18309
|
+
(setq layers nil le (tblnext "layer" t))
|
|
18310
|
+
(while le
|
|
18311
|
+
(setq ln (cdr (assoc 2 le)) lc (cdr (assoc 62 le)) ll (cdr (assoc 6 le)))
|
|
18312
|
+
(setq layers (cons (list "name" ln "color" (if (< lc 0) (- lc) lc) "off" (< lc 0) "linetype" ll) layers))
|
|
18313
|
+
(setq le (tblnext "layer" nil)))
|
|
18314
|
+
(setq r (cons (cons "layers" layers) r))
|
|
18315
|
+
;; text stats
|
|
18316
|
+
(if (setq ts (ssget "_X" '((0 . "TEXT,MTEXT"))))
|
|
18317
|
+
(progn
|
|
18318
|
+
(setq tc (sslength ts) th nil ti 0)
|
|
18319
|
+
(while (< ti tc)
|
|
18320
|
+
(setq h (cdr (assoc 40 (entget (ssname ts ti)))))
|
|
18321
|
+
(if h (setq th (cons h th)))
|
|
18322
|
+
(setq ti (1+ ti)))
|
|
18323
|
+
(setq th (vl-sort th '<))
|
|
18324
|
+
(setq r (cons (cons "textCount" tc) r))
|
|
18325
|
+
(setq r (cons (cons "textHeights" (list "min" (car th) "max" (last th) "median" (nth (fix (/ (length th) 2)) th))) r)))
|
|
18326
|
+
(setq r (cons (cons "textCount" 0) r)))
|
|
18327
|
+
;; system variables
|
|
18328
|
+
(setq r (cons (cons "sysvars" (list
|
|
18329
|
+
(cons "ltscale" (getvar "ltscale"))
|
|
18330
|
+
(cons "dimscale" (getvar "dimscale"))
|
|
18331
|
+
(cons "insunits" (getvar "insunits"))
|
|
18332
|
+
(cons "measurement" (getvar "measurement"))
|
|
18333
|
+
(cons "celtype" (getvar "celtype"))
|
|
18334
|
+
(cons "clayer" (getvar "clayer"))
|
|
18335
|
+
(cons "cecolor" (getvar "cecolor"))
|
|
18336
|
+
(cons "osmode" (getvar "osmode"))
|
|
18337
|
+
(cons "snapmode" (getvar "snapmode"))
|
|
18338
|
+
(cons "gridmode" (getvar "gridmode"))
|
|
18339
|
+
(cons "orthomode" (getvar "orthomode"))
|
|
18340
|
+
(cons "plinetype" (getvar "plinetype"))
|
|
18341
|
+
(cons "fillmode" (getvar "fillmode"))
|
|
18342
|
+
(cons "pickstyle" (getvar "pickstyle"))
|
|
18343
|
+
)) r))
|
|
18344
|
+
(vl-prin1-to-string (reverse r)))`;
|
|
18345
|
+
const resultStr = await cad.sendCommandWithResult(detailedCode);
|
|
18346
|
+
const parsed = parseLispRecursive(resultStr);
|
|
18347
|
+
if (!parsed || !Array.isArray(parsed)) {
|
|
18348
|
+
return { connected: true, error: "\u5206\u6790\u7ED3\u679C\u89E3\u6790\u5931\u8D25" };
|
|
18349
|
+
}
|
|
18350
|
+
const analysis = {};
|
|
18351
|
+
for (const pair of parsed) {
|
|
18352
|
+
if (Array.isArray(pair) && pair.length >= 2) {
|
|
18353
|
+
analysis[String(pair[0])] = pair[1];
|
|
18354
|
+
}
|
|
18355
|
+
}
|
|
18356
|
+
return { connected: true, ...analysis };
|
|
18357
|
+
} catch (e) {
|
|
18358
|
+
log(`getDrawingAnalysis error: ${e.message}`);
|
|
18359
|
+
return { connected: true, error: e.message };
|
|
18360
|
+
}
|
|
18361
|
+
}
|
|
18362
|
+
function getToolCategories() {
|
|
18363
|
+
const cats = {};
|
|
18364
|
+
for (const t of tools43) {
|
|
18365
|
+
const cat = t.annotations?.category || "\u5176\u4ED6";
|
|
18366
|
+
if (!cats[cat]) cats[cat] = { count: 0, tools: [] };
|
|
18367
|
+
cats[cat].count++;
|
|
18368
|
+
cats[cat].tools.push(t.name);
|
|
18369
|
+
}
|
|
18370
|
+
return Object.entries(cats).map(([category, info]) => ({
|
|
18371
|
+
category,
|
|
18372
|
+
count: info.count,
|
|
18373
|
+
tools: info.tools
|
|
18374
|
+
})).sort((a, b) => b.count - a.count);
|
|
18375
|
+
}
|
|
18376
|
+
async function checkDrawingStandards() {
|
|
18377
|
+
const standards = getDraftingStandards();
|
|
18378
|
+
if (!standards || standards.error) {
|
|
18379
|
+
return { ok: false, error: standards?.error || "\u5236\u56FE\u89C4\u8303\u672A\u52A0\u8F7D" };
|
|
18380
|
+
}
|
|
18381
|
+
try {
|
|
18382
|
+
const issues = [];
|
|
18383
|
+
for (const rule of standards.layers || []) {
|
|
18384
|
+
const code = `(tblsearch "LAYER" "${escapeLispString(rule.name || rule.pattern)}")`;
|
|
18385
|
+
const exists = await cad.sendCommandWithResult(code);
|
|
18386
|
+
if (rule.required && (!exists || exists === "nil" || exists === "")) {
|
|
18387
|
+
issues.push({ type: "missing_layer", message: `\u7F3A\u5C11\u5FC5\u9700\u56FE\u5C42: ${rule.name}` });
|
|
18388
|
+
}
|
|
18389
|
+
}
|
|
18390
|
+
return { ok: issues.length === 0, issues };
|
|
18391
|
+
} catch (e) {
|
|
18392
|
+
return { ok: false, error: e.message };
|
|
18393
|
+
}
|
|
18394
|
+
}
|
|
17952
18395
|
function getToolRelationships() {
|
|
17953
18396
|
return {
|
|
17954
18397
|
selection: {
|
|
@@ -18204,6 +18647,12 @@ async function readResource(uri) {
|
|
|
18204
18647
|
return await getDwgContext();
|
|
18205
18648
|
case "atlisp://tools/relationships":
|
|
18206
18649
|
return getToolRelationships();
|
|
18650
|
+
case "atlisp://dwg/analysis":
|
|
18651
|
+
return await getDrawingAnalysis(params);
|
|
18652
|
+
case "atlisp://tools/categories":
|
|
18653
|
+
return getToolCategories();
|
|
18654
|
+
case "atlisp://dwg/standards/check":
|
|
18655
|
+
return await checkDrawingStandards();
|
|
18207
18656
|
default:
|
|
18208
18657
|
throw new Error(`\u8D44\u6E90\u4E0D\u5B58\u5728: ${uri}`);
|
|
18209
18658
|
}
|
|
@@ -18219,6 +18668,7 @@ var init_resource_handlers = __esm({
|
|
|
18219
18668
|
init_handler_utils();
|
|
18220
18669
|
init_errors();
|
|
18221
18670
|
init_config();
|
|
18671
|
+
init_tools();
|
|
18222
18672
|
ENTITY_PROPERTIES_LISP = `
|
|
18223
18673
|
(defun entity:to-list (val)
|
|
18224
18674
|
(cond
|
|
@@ -18298,11 +18748,11 @@ init_subscription_manager();
|
|
|
18298
18748
|
init_subscription_manager();
|
|
18299
18749
|
init_sse_session();
|
|
18300
18750
|
init_config();
|
|
18301
|
-
import
|
|
18751
|
+
import path20 from "path";
|
|
18302
18752
|
import fs16 from "fs";
|
|
18303
18753
|
import http from "http";
|
|
18304
18754
|
import https from "https";
|
|
18305
|
-
import { fileURLToPath as
|
|
18755
|
+
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
18306
18756
|
import { createRequire as createRequire2 } from "module";
|
|
18307
18757
|
import express2 from "express";
|
|
18308
18758
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -18315,11 +18765,12 @@ init_cad_pool();
|
|
|
18315
18765
|
init_subscription_manager();
|
|
18316
18766
|
init_mcp_server_state();
|
|
18317
18767
|
init_sse_session();
|
|
18768
|
+
import os10 from "os";
|
|
18318
18769
|
import express from "express";
|
|
18319
18770
|
import { randomUUID as randomUUID6, createHash } from "crypto";
|
|
18320
18771
|
import fs14 from "fs";
|
|
18321
|
-
import
|
|
18322
|
-
import { fileURLToPath as
|
|
18772
|
+
import path18 from "path";
|
|
18773
|
+
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
18323
18774
|
import iconv from "iconv-lite";
|
|
18324
18775
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
18325
18776
|
|
|
@@ -18432,7 +18883,6 @@ var TOOL_PERMISSIONS = {
|
|
|
18432
18883
|
"measure_*": "read",
|
|
18433
18884
|
"stream_*": "read",
|
|
18434
18885
|
"watch_list": "read",
|
|
18435
|
-
"pipeline_list": "read",
|
|
18436
18886
|
// Write tools
|
|
18437
18887
|
"create_*": "write",
|
|
18438
18888
|
"set_*": "write",
|
|
@@ -18452,8 +18902,6 @@ var TOOL_PERMISSIONS = {
|
|
|
18452
18902
|
"import_*": "import",
|
|
18453
18903
|
// Admin
|
|
18454
18904
|
"config_*": "admin",
|
|
18455
|
-
"pipeline_save": "admin",
|
|
18456
|
-
"pipeline_delete": "admin",
|
|
18457
18905
|
"webhook_*": "admin",
|
|
18458
18906
|
"watch_remove": "admin"
|
|
18459
18907
|
};
|
|
@@ -18487,11 +18935,11 @@ function getApiKeyRole(apiKey2, config2) {
|
|
|
18487
18935
|
|
|
18488
18936
|
// src/routes.js
|
|
18489
18937
|
init_constants();
|
|
18490
|
-
var __dirname6 =
|
|
18491
|
-
var htmlDir =
|
|
18938
|
+
var __dirname6 = path18.dirname(fileURLToPath7(import.meta.url));
|
|
18939
|
+
var htmlDir = path18.join(__dirname6, "html");
|
|
18492
18940
|
function loadHtml(name, replacements = {}) {
|
|
18493
18941
|
if (!htmlCache[name]) {
|
|
18494
|
-
htmlCache[name] = fs14.readFileSync(
|
|
18942
|
+
htmlCache[name] = fs14.readFileSync(path18.join(htmlDir, `${name}.html`), "utf-8");
|
|
18495
18943
|
}
|
|
18496
18944
|
let html = htmlCache[name];
|
|
18497
18945
|
for (const [key, value] of Object.entries(replacements)) {
|
|
@@ -18504,7 +18952,7 @@ var cachedToolsJson = null;
|
|
|
18504
18952
|
var cachedToolsJsonAt = 0;
|
|
18505
18953
|
function getToolsJson() {
|
|
18506
18954
|
if (cachedToolsJson && Date.now() - cachedToolsJsonAt < 3e4) return cachedToolsJson;
|
|
18507
|
-
cachedToolsJson = JSON.stringify(
|
|
18955
|
+
cachedToolsJson = JSON.stringify(tools43.map((t) => ({
|
|
18508
18956
|
name: t.name,
|
|
18509
18957
|
description: t.description,
|
|
18510
18958
|
inputSchema: t.inputSchema
|
|
@@ -18574,15 +19022,45 @@ function createAuthMiddleware() {
|
|
|
18574
19022
|
return res.status(401).json({ error: "Unauthorized" });
|
|
18575
19023
|
};
|
|
18576
19024
|
}
|
|
19025
|
+
function originMatches(pattern, origin) {
|
|
19026
|
+
if (pattern === "*") return true;
|
|
19027
|
+
if (!origin) return false;
|
|
19028
|
+
const getHost = (s) => s.replace(/^https?:\/\//, "").replace(/:\d+$/, "").toLowerCase();
|
|
19029
|
+
const oHost = getHost(origin);
|
|
19030
|
+
let pHost = getHost(pattern);
|
|
19031
|
+
if (pHost.startsWith("*.")) {
|
|
19032
|
+
const suffix = pHost.slice(1);
|
|
19033
|
+
return oHost === suffix.slice(1) || oHost.endsWith(suffix);
|
|
19034
|
+
}
|
|
19035
|
+
return oHost === pHost;
|
|
19036
|
+
}
|
|
18577
19037
|
function createCorsMiddleware() {
|
|
19038
|
+
const allowedOrigins = corsOrigin.split(",").map((s) => s.trim()).filter(Boolean);
|
|
19039
|
+
const allowAll = allowedOrigins.includes("*");
|
|
18578
19040
|
return (req, res, next) => {
|
|
18579
19041
|
if (!enableCors) return next();
|
|
18580
|
-
|
|
19042
|
+
const origin = req.headers.origin;
|
|
19043
|
+
const isPnaPreflight = req.method === "OPTIONS" && req.headers["access-control-request-private-network"] === "true";
|
|
19044
|
+
if (allowAll) {
|
|
19045
|
+
if (isPnaPreflight && origin) {
|
|
19046
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
19047
|
+
res.setHeader("Vary", "Origin");
|
|
19048
|
+
} else {
|
|
19049
|
+
res.setHeader("Access-Control-Allow-Origin", corsOrigin);
|
|
19050
|
+
}
|
|
19051
|
+
} else if (origin && allowedOrigins.some((p) => originMatches(p, origin))) {
|
|
19052
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
19053
|
+
res.setHeader("Vary", "Origin");
|
|
19054
|
+
} else if (!origin) {
|
|
19055
|
+
res.setHeader("Access-Control-Allow-Origin", allowedOrigins[0] || "*");
|
|
19056
|
+
} else {
|
|
19057
|
+
return res.status(403).json({ error: "Origin not allowed" });
|
|
19058
|
+
}
|
|
18581
19059
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, CONNECT");
|
|
18582
19060
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, mcp-session-id, last-event-id");
|
|
18583
19061
|
res.setHeader("Access-Control-Expose-Headers", "mcp-session-id, content-type, x-accel-buffering");
|
|
18584
19062
|
res.setHeader("Access-Control-Max-Age", "86400");
|
|
18585
|
-
res.setHeader("
|
|
19063
|
+
res.setHeader("Access-Control-Allow-Private-Network", "true");
|
|
18586
19064
|
if (req.method === "OPTIONS") return res.status(204).end();
|
|
18587
19065
|
next();
|
|
18588
19066
|
};
|
|
@@ -18673,7 +19151,7 @@ function setupRoutes(app) {
|
|
|
18673
19151
|
},
|
|
18674
19152
|
mcp: {
|
|
18675
19153
|
sessions: sessionServers.size,
|
|
18676
|
-
tools:
|
|
19154
|
+
tools: tools43.length,
|
|
18677
19155
|
sseSessions: sseCount
|
|
18678
19156
|
},
|
|
18679
19157
|
pool: {
|
|
@@ -18683,6 +19161,11 @@ function setupRoutes(app) {
|
|
|
18683
19161
|
}
|
|
18684
19162
|
});
|
|
18685
19163
|
});
|
|
19164
|
+
app.get("/go", (req, res) => {
|
|
19165
|
+
const remoteUrl = "https://atlisp.cn/agent";
|
|
19166
|
+
const cid = config_default.clientId || os10.hostname();
|
|
19167
|
+
res.redirect(302, `${remoteUrl}?clientId=${encodeURIComponent(cid)}`);
|
|
19168
|
+
});
|
|
18686
19169
|
app.get("/health/full", async (req, res) => {
|
|
18687
19170
|
const memUsage = process.memoryUsage();
|
|
18688
19171
|
const poolStats = pool ? pool.getStats() : {};
|
|
@@ -18696,7 +19179,7 @@ function setupRoutes(app) {
|
|
|
18696
19179
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18697
19180
|
cad: { connected: cad.connected, platform: cad.getPlatform?.(), version: cad.getVersion?.(), commandQueueSize: cad._getQueueSize ? cad._getQueueSize() : 0, restartCount: cad._getRestartCount ? cad._getRestartCount() : 0 },
|
|
18698
19181
|
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:
|
|
19182
|
+
mcp: { sessions: sessionServers.size, tools: tools43.length, sseSessions: sseCount },
|
|
18700
19183
|
pool: poolStats
|
|
18701
19184
|
});
|
|
18702
19185
|
});
|
|
@@ -18734,7 +19217,7 @@ function setupRoutes(app) {
|
|
|
18734
19217
|
app.get("/api/docs", (req, res) => {
|
|
18735
19218
|
const html = loadHtml("api-docs", {
|
|
18736
19219
|
VERSION: SERVER_VERSION,
|
|
18737
|
-
TOOLS_COUNT:
|
|
19220
|
+
TOOLS_COUNT: tools43.length
|
|
18738
19221
|
});
|
|
18739
19222
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
18740
19223
|
res.send(html);
|
|
@@ -18755,7 +19238,7 @@ function setupRoutes(app) {
|
|
|
18755
19238
|
SESSIONS_COUNT: sessionServers.size,
|
|
18756
19239
|
CAD_STATUS_CLASS: cadConnected ? "status-ok" : "status-error",
|
|
18757
19240
|
CAD_STATUS_TEXT: cadStatusText,
|
|
18758
|
-
TOOLS_COUNT:
|
|
19241
|
+
TOOLS_COUNT: tools43.length
|
|
18759
19242
|
});
|
|
18760
19243
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
18761
19244
|
res.send(html);
|
|
@@ -18947,7 +19430,7 @@ function sendWelcome(ws, clientId) {
|
|
|
18947
19430
|
server: { name: SERVER_NAME, version: SERVER_VERSION },
|
|
18948
19431
|
capabilities: SERVER_CAPABILITIES,
|
|
18949
19432
|
clientId,
|
|
18950
|
-
toolCount:
|
|
19433
|
+
toolCount: tools43.length,
|
|
18951
19434
|
cadConnected: cad.connected,
|
|
18952
19435
|
cadPlatform: cad.connected ? cad.getPlatform() : null,
|
|
18953
19436
|
cadVersion: cad.connected ? cad.getVersion() : null
|
|
@@ -19199,9 +19682,9 @@ function createWebSocketServer(httpServer) {
|
|
|
19199
19682
|
// src/plugin-loader.js
|
|
19200
19683
|
init_logger();
|
|
19201
19684
|
import fs15 from "fs";
|
|
19202
|
-
import
|
|
19203
|
-
import
|
|
19204
|
-
var PLUGIN_DIR =
|
|
19685
|
+
import path19 from "path";
|
|
19686
|
+
import os11 from "os";
|
|
19687
|
+
var PLUGIN_DIR = path19.join(os11.homedir(), ".atlisp", "mcp-plugins");
|
|
19205
19688
|
var loadedPlugins = [];
|
|
19206
19689
|
var watchCallbacks = [];
|
|
19207
19690
|
var watcher = null;
|
|
@@ -19226,7 +19709,7 @@ function clearModuleCache(pluginPath) {
|
|
|
19226
19709
|
if (key) delete import.meta[key];
|
|
19227
19710
|
}
|
|
19228
19711
|
async function loadSinglePlugin(file) {
|
|
19229
|
-
const pluginPath =
|
|
19712
|
+
const pluginPath = path19.join(PLUGIN_DIR, file);
|
|
19230
19713
|
clearModuleCache(pluginPath);
|
|
19231
19714
|
try {
|
|
19232
19715
|
const plugin = await import(`${pluginPath}?t=${Date.now()}`);
|
|
@@ -19276,7 +19759,7 @@ function startPluginWatcher() {
|
|
|
19276
19759
|
if (!filename || !filename.endsWith(".js") || filename.startsWith("_")) return;
|
|
19277
19760
|
const existingIndex = loadedPlugins.findIndex((p) => p.name === filename.replace(".js", "") || p._file === filename);
|
|
19278
19761
|
if (eventType === "rename") {
|
|
19279
|
-
const filePath =
|
|
19762
|
+
const filePath = path19.join(PLUGIN_DIR, filename);
|
|
19280
19763
|
if (!fs15.existsSync(filePath)) {
|
|
19281
19764
|
if (existingIndex !== -1) {
|
|
19282
19765
|
loadedPlugins.splice(existingIndex, 1);
|
|
@@ -19316,6 +19799,91 @@ function stopPluginWatcher() {
|
|
|
19316
19799
|
init_tool_registry();
|
|
19317
19800
|
init_mcp_server_state();
|
|
19318
19801
|
|
|
19802
|
+
// src/health-reporter.js
|
|
19803
|
+
init_config();
|
|
19804
|
+
init_cad();
|
|
19805
|
+
init_cad_pool();
|
|
19806
|
+
init_mcp_server_state();
|
|
19807
|
+
init_subscription_manager();
|
|
19808
|
+
init_logger();
|
|
19809
|
+
import os12 from "os";
|
|
19810
|
+
var REPORT_URL = "https://atlisp.cn/api/mcp/health";
|
|
19811
|
+
var REPORT_INTERVAL = 3e4;
|
|
19812
|
+
var intervalHandle = null;
|
|
19813
|
+
function gatherHealth() {
|
|
19814
|
+
let cadResponseTime = 0;
|
|
19815
|
+
if (cad.connected) {
|
|
19816
|
+
const t0 = Date.now();
|
|
19817
|
+
try {
|
|
19818
|
+
cad.ping();
|
|
19819
|
+
} catch {
|
|
19820
|
+
}
|
|
19821
|
+
cadResponseTime = Date.now() - t0;
|
|
19822
|
+
}
|
|
19823
|
+
const memUsage = process.memoryUsage();
|
|
19824
|
+
let sseCount = 0;
|
|
19825
|
+
try {
|
|
19826
|
+
sseCount = sessionManager?.count?.() || 0;
|
|
19827
|
+
} catch {
|
|
19828
|
+
}
|
|
19829
|
+
return {
|
|
19830
|
+
clientId: config_default.clientId || os12.hostname(),
|
|
19831
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19832
|
+
status: "ok",
|
|
19833
|
+
cad: {
|
|
19834
|
+
connected: cad.connected,
|
|
19835
|
+
platform: cad.getPlatform ? cad.getPlatform() : null,
|
|
19836
|
+
version: cad.getVersion ? cad.getVersion() : null,
|
|
19837
|
+
responseTime: cadResponseTime,
|
|
19838
|
+
commandQueueSize: cad._getQueueSize ? cad._getQueueSize() : 0,
|
|
19839
|
+
restartCount: cad._getRestartCount ? cad._getRestartCount() : 0
|
|
19840
|
+
},
|
|
19841
|
+
system: {
|
|
19842
|
+
uptime: process.uptime(),
|
|
19843
|
+
memory: {
|
|
19844
|
+
rss: Math.round(memUsage.rss / 1024 / 1024),
|
|
19845
|
+
heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
|
|
19846
|
+
heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024)
|
|
19847
|
+
}
|
|
19848
|
+
},
|
|
19849
|
+
mcp: {
|
|
19850
|
+
sessions: sessionServers.size,
|
|
19851
|
+
sseSessions: sseCount
|
|
19852
|
+
},
|
|
19853
|
+
pool: pool ? {
|
|
19854
|
+
total: pool.getStats().total,
|
|
19855
|
+
active: pool.getStats().active,
|
|
19856
|
+
instances: pool.getStats().instances
|
|
19857
|
+
} : null
|
|
19858
|
+
};
|
|
19859
|
+
}
|
|
19860
|
+
async function report() {
|
|
19861
|
+
try {
|
|
19862
|
+
const data = gatherHealth();
|
|
19863
|
+
const res = await fetch(REPORT_URL, {
|
|
19864
|
+
method: "POST",
|
|
19865
|
+
headers: { "Content-Type": "application/json" },
|
|
19866
|
+
body: JSON.stringify(data),
|
|
19867
|
+
signal: AbortSignal.timeout(1e4)
|
|
19868
|
+
});
|
|
19869
|
+
if (!res.ok) {
|
|
19870
|
+
error(`Health report failed: ${res.status}`);
|
|
19871
|
+
}
|
|
19872
|
+
} catch (e) {
|
|
19873
|
+
error(`Health report error: ${e.message}`);
|
|
19874
|
+
}
|
|
19875
|
+
}
|
|
19876
|
+
function startHealthReporter() {
|
|
19877
|
+
report();
|
|
19878
|
+
intervalHandle = setInterval(report, REPORT_INTERVAL);
|
|
19879
|
+
}
|
|
19880
|
+
function stopHealthReporter() {
|
|
19881
|
+
if (intervalHandle) {
|
|
19882
|
+
clearInterval(intervalHandle);
|
|
19883
|
+
intervalHandle = null;
|
|
19884
|
+
}
|
|
19885
|
+
}
|
|
19886
|
+
|
|
19319
19887
|
// src/streamable-http.js
|
|
19320
19888
|
init_logger();
|
|
19321
19889
|
init_mcp_handlers();
|
|
@@ -19326,7 +19894,7 @@ var mcpServer = null;
|
|
|
19326
19894
|
var streamableTransport = null;
|
|
19327
19895
|
async function initStreamableHttpServer() {
|
|
19328
19896
|
if (mcpServer) return;
|
|
19329
|
-
mcpServer = createMcpServer({ tools:
|
|
19897
|
+
mcpServer = createMcpServer({ tools: tools43, handleToolCall });
|
|
19330
19898
|
streamableTransport = new StreamableHTTPServerTransport2({
|
|
19331
19899
|
sessionIdGenerator: () => randomUUID8()
|
|
19332
19900
|
});
|
|
@@ -19377,9 +19945,9 @@ function setupStreamableHttpRoutes(app) {
|
|
|
19377
19945
|
init_mcp_tools();
|
|
19378
19946
|
init_function_handlers();
|
|
19379
19947
|
init_constants();
|
|
19380
|
-
var __dirname7 =
|
|
19948
|
+
var __dirname7 = path20.dirname(fileURLToPath8(import.meta.url));
|
|
19381
19949
|
var require3 = createRequire2(import.meta.url);
|
|
19382
|
-
var { version: version2 } = require3(
|
|
19950
|
+
var { version: version2 } = require3(path20.join(__dirname7, "..", "package.json"));
|
|
19383
19951
|
var isMcpScript = process.argv[1]?.includes("atlisp-mcp");
|
|
19384
19952
|
if (isMcpScript) {
|
|
19385
19953
|
const cliArgs2 = process.argv.slice(2);
|
|
@@ -19413,6 +19981,7 @@ Options:
|
|
|
19413
19981
|
--no-lint Disable lint pre-check for eval_lisp
|
|
19414
19982
|
--lint-off Same as --no-lint
|
|
19415
19983
|
--api-key <key> API key for authentication
|
|
19984
|
+
--client-id <id> Client identifier for remote health report
|
|
19416
19985
|
--security-level <type> Security level: strict, standard, relaxed (default: strict)
|
|
19417
19986
|
|
|
19418
19987
|
Environment Variables:
|
|
@@ -19433,7 +20002,8 @@ Environment Variables:
|
|
|
19433
20002
|
LINT_LEVEL Lint level (error/warn/off)
|
|
19434
20003
|
NO_LINT Disable lint (true/false)
|
|
19435
20004
|
REQUEST_LOG_ENABLED Enable request logging (true/false, default: true)
|
|
19436
|
-
CORS_ORIGIN CORS origin (default:
|
|
20005
|
+
CORS_ORIGIN CORS origin (default: https://atlisp.cn)
|
|
20006
|
+
CLIENT_ID Client identifier for remote health report
|
|
19437
20007
|
RATE_LIMIT_WINDOW Rate limit window in ms (default: 60000)
|
|
19438
20008
|
RATE_LIMIT_MAX Max requests per window (default: 100)
|
|
19439
20009
|
|
|
@@ -19489,6 +20059,8 @@ For more info: https://atlisp.cn
|
|
|
19489
20059
|
process.env.SSL_CERT_PATH = cliArgs2[++i];
|
|
19490
20060
|
} else if (arg === "--api-key" && cliArgs2[i + 1]) {
|
|
19491
20061
|
process.env.MCP_API_KEY = cliArgs2[++i];
|
|
20062
|
+
} else if (arg === "--client-id" && cliArgs2[i + 1]) {
|
|
20063
|
+
process.env.CLIENT_ID = cliArgs2[++i];
|
|
19492
20064
|
} else if (arg === "--metrics-enabled" && cliArgs2[i + 1]) {
|
|
19493
20065
|
process.env.METRICS_ENABLED = cliArgs2[++i];
|
|
19494
20066
|
}
|
|
@@ -19511,7 +20083,7 @@ async function initCadConnection() {
|
|
|
19511
20083
|
}
|
|
19512
20084
|
async function startServer() {
|
|
19513
20085
|
await loadPlugins();
|
|
19514
|
-
initPlugins({ cad, config: config_default, log, registerTool, tools:
|
|
20086
|
+
initPlugins({ cad, config: config_default, log, registerTool, tools: tools43 });
|
|
19515
20087
|
onPluginChange((type, name) => {
|
|
19516
20088
|
log(`Plugin changed: ${type} ${name}`);
|
|
19517
20089
|
broadcastToolListChanged();
|
|
@@ -19521,7 +20093,7 @@ async function startServer() {
|
|
|
19521
20093
|
startPluginWatcher();
|
|
19522
20094
|
let promptsWatcher = null;
|
|
19523
20095
|
try {
|
|
19524
|
-
const promptsDir =
|
|
20096
|
+
const promptsDir = path20.join(__dirname7, "..", "prompts");
|
|
19525
20097
|
if (fs16.existsSync(promptsDir)) {
|
|
19526
20098
|
promptsWatcher = fs16.watch(promptsDir, (eventType, filename) => {
|
|
19527
20099
|
if (filename && filename.endsWith(".json")) {
|
|
@@ -19535,7 +20107,7 @@ async function startServer() {
|
|
|
19535
20107
|
}
|
|
19536
20108
|
if (config_default.transport === "stdio") {
|
|
19537
20109
|
await initCadConnection();
|
|
19538
|
-
const mcpServer2 = createStdioServer({ tools:
|
|
20110
|
+
const mcpServer2 = createStdioServer({ tools: tools43, handleToolCall });
|
|
19539
20111
|
const transport = new StdioServerTransport();
|
|
19540
20112
|
const sessionId = "stdio-session";
|
|
19541
20113
|
sessionManager.createSession(sessionId);
|
|
@@ -19583,10 +20155,12 @@ async function startServer() {
|
|
|
19583
20155
|
const proto = useSsl ? "https" : "http";
|
|
19584
20156
|
const mode = config_default.transport === "ws" ? "WebSocket" : config_default.transport === "streamable-http" ? "Streamable HTTP" : "\u591A\u4F1A\u8BDD";
|
|
19585
20157
|
console.error(`@lisp MCP Server \u542F\u52A8 - ${proto}://${config_default.host}:${config_default.port} (${mode}\u6A21\u5F0F)`);
|
|
20158
|
+
startHealthReporter();
|
|
19586
20159
|
});
|
|
19587
20160
|
async function shutdown(signal) {
|
|
19588
20161
|
console.error(`
|
|
19589
20162
|
\u6536\u5230 ${signal}\uFF0C\u6B63\u5728\u4F18\u96C5\u5173\u95ED...`);
|
|
20163
|
+
stopHealthReporter();
|
|
19590
20164
|
stopPluginWatcher();
|
|
19591
20165
|
if (promptsWatcher) {
|
|
19592
20166
|
promptsWatcher.close();
|
|
@@ -19636,5 +20210,5 @@ export {
|
|
|
19636
20210
|
handleToolCall,
|
|
19637
20211
|
loadAtlibFunctionLib,
|
|
19638
20212
|
startServer,
|
|
19639
|
-
|
|
20213
|
+
tools43 as tools
|
|
19640
20214
|
};
|