@vcad/mcp 0.11.0-main.162 → 0.11.0-main.163
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 +1 -1
- package/index.mjs +211 -92
- package/package.json +3 -3
- package/skill/SKILL.md +22 -0
package/README.md
CHANGED
|
@@ -9,4 +9,4 @@ vcad's MCP server as a self-contained bundle (server + BRep kernel WASM).
|
|
|
9
9
|
Or install vcad.app, which registers this server with your agents on first launch.
|
|
10
10
|
The agent skill ships at `skill/SKILL.md`.
|
|
11
11
|
|
|
12
|
-
Built from
|
|
12
|
+
Built from 816ee12b085c12b403a35ebfedb6c276e175a3af at 2026-11-11T21:40:44.212Z. Source: https://github.com/muni-works/vcad
|
package/index.mjs
CHANGED
|
@@ -11312,9 +11312,9 @@ function workerTransport(worker) {
|
|
|
11312
11312
|
pending.delete(id);
|
|
11313
11313
|
});
|
|
11314
11314
|
return {
|
|
11315
|
-
request: (req) => new Promise((
|
|
11315
|
+
request: (req) => new Promise((resolve9) => {
|
|
11316
11316
|
const id = next++;
|
|
11317
|
-
pending.set(id,
|
|
11317
|
+
pending.set(id, resolve9);
|
|
11318
11318
|
worker.postMessage({ id, req });
|
|
11319
11319
|
}),
|
|
11320
11320
|
dispose: () => worker.terminate()
|
|
@@ -12193,11 +12193,11 @@ var init_analyze = __esm({
|
|
|
12193
12193
|
type: "module"
|
|
12194
12194
|
});
|
|
12195
12195
|
this.worker = worker;
|
|
12196
|
-
this.ready = new Promise((
|
|
12196
|
+
this.ready = new Promise((resolve9, reject) => {
|
|
12197
12197
|
const onMessage = (e) => {
|
|
12198
12198
|
const { type, id, message, analysis } = e.data;
|
|
12199
12199
|
if (type === "ready") {
|
|
12200
|
-
|
|
12200
|
+
resolve9();
|
|
12201
12201
|
return;
|
|
12202
12202
|
}
|
|
12203
12203
|
if (type === "error" && id === null) {
|
|
@@ -12221,9 +12221,9 @@ var init_analyze = __esm({
|
|
|
12221
12221
|
return this.ready;
|
|
12222
12222
|
}
|
|
12223
12223
|
request(msg, transfer = []) {
|
|
12224
|
-
return this.ensureWorker().then(() => new Promise((
|
|
12224
|
+
return this.ensureWorker().then(() => new Promise((resolve9, reject) => {
|
|
12225
12225
|
const id = this.nextId++;
|
|
12226
|
-
this.pending.set(id, { resolve:
|
|
12226
|
+
this.pending.set(id, { resolve: resolve9, reject });
|
|
12227
12227
|
this.worker.postMessage({ ...msg, id }, transfer);
|
|
12228
12228
|
}));
|
|
12229
12229
|
}
|
|
@@ -12840,11 +12840,11 @@ var init_dist = __esm({
|
|
|
12840
12840
|
return;
|
|
12841
12841
|
try {
|
|
12842
12842
|
const worker = new Worker(new URL("./eval-worker.js", import.meta.url), { type: "module" });
|
|
12843
|
-
this.workerReady = new Promise((
|
|
12843
|
+
this.workerReady = new Promise((resolve9, reject) => {
|
|
12844
12844
|
const onMessage = (e) => {
|
|
12845
12845
|
if (e.data.type === "ready") {
|
|
12846
12846
|
worker.removeEventListener("message", onMessage);
|
|
12847
|
-
|
|
12847
|
+
resolve9();
|
|
12848
12848
|
} else if (e.data.type === "error" && e.data.id === null) {
|
|
12849
12849
|
worker.removeEventListener("message", onMessage);
|
|
12850
12850
|
console.warn("[ENGINE] Worker WASM init failed:", e.data.message);
|
|
@@ -13067,7 +13067,7 @@ var init_dist = __esm({
|
|
|
13067
13067
|
const worker = this.worker;
|
|
13068
13068
|
const id = Math.random().toString(36).slice(2);
|
|
13069
13069
|
const skipClash = options.skipClashDetection ?? false;
|
|
13070
|
-
return new Promise((
|
|
13070
|
+
return new Promise((resolve9, reject) => {
|
|
13071
13071
|
const onMessage = (e) => {
|
|
13072
13072
|
if (e.data.id !== id)
|
|
13073
13073
|
return;
|
|
@@ -13077,7 +13077,7 @@ var init_dist = __esm({
|
|
|
13077
13077
|
if (scene.timing && _Engine.DEV) {
|
|
13078
13078
|
_Engine.logTiming(scene.timing, e.data.workerTotalMs);
|
|
13079
13079
|
}
|
|
13080
|
-
|
|
13080
|
+
resolve9(scene);
|
|
13081
13081
|
} else if (e.data.type === "error") {
|
|
13082
13082
|
reject(new Error(e.data.message));
|
|
13083
13083
|
}
|
|
@@ -17365,7 +17365,7 @@ function isRef(value) {
|
|
|
17365
17365
|
function cloneIssues(issues) {
|
|
17366
17366
|
return issues.map((iss) => iss.path ? { ...iss, path: iss.path.slice() } : { ...iss });
|
|
17367
17367
|
}
|
|
17368
|
-
function isRecursive(inst, stack,
|
|
17368
|
+
function isRecursive(inst, stack, resolve9) {
|
|
17369
17369
|
const cached3 = recursive.get(inst);
|
|
17370
17370
|
if (cached3 !== void 0)
|
|
17371
17371
|
return cached3 ? PROVEN : NONE;
|
|
@@ -17375,7 +17375,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
17375
17375
|
let result = NONE;
|
|
17376
17376
|
const check = (child) => {
|
|
17377
17377
|
if (result !== PROVEN && child?._zod) {
|
|
17378
|
-
const answer = isRecursive(child, stack,
|
|
17378
|
+
const answer = isRecursive(child, stack, resolve9);
|
|
17379
17379
|
if (answer > result)
|
|
17380
17380
|
result = answer;
|
|
17381
17381
|
}
|
|
@@ -17386,7 +17386,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
17386
17386
|
const desc = Object.getOwnPropertyDescriptor(sh, key3);
|
|
17387
17387
|
if (spread && !desc.enumerable)
|
|
17388
17388
|
continue;
|
|
17389
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
17389
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve9) : NONE;
|
|
17390
17390
|
if (child > answer)
|
|
17391
17391
|
answer = child;
|
|
17392
17392
|
}
|
|
@@ -17450,7 +17450,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
17450
17450
|
break;
|
|
17451
17451
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
17452
17452
|
case "lazy": {
|
|
17453
|
-
const inner = def._cachedInner ?? (
|
|
17453
|
+
const inner = def._cachedInner ?? (resolve9 ? inst._zod.innerType : void 0);
|
|
17454
17454
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
17455
17455
|
break;
|
|
17456
17456
|
}
|
|
@@ -22204,12 +22204,12 @@ var init_stdio2 = __esm({
|
|
|
22204
22204
|
this.onclose?.();
|
|
22205
22205
|
}
|
|
22206
22206
|
send(message) {
|
|
22207
|
-
return new Promise((
|
|
22207
|
+
return new Promise((resolve9) => {
|
|
22208
22208
|
const json = serializeMessage(message);
|
|
22209
22209
|
if (this._stdout.write(json)) {
|
|
22210
|
-
|
|
22210
|
+
resolve9();
|
|
22211
22211
|
} else {
|
|
22212
|
-
this._stdout.once("drain",
|
|
22212
|
+
this._stdout.once("drain", resolve9);
|
|
22213
22213
|
}
|
|
22214
22214
|
});
|
|
22215
22215
|
}
|
|
@@ -23246,7 +23246,7 @@ var init_protocol = __esm({
|
|
|
23246
23246
|
return;
|
|
23247
23247
|
}
|
|
23248
23248
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
23249
|
-
await new Promise((
|
|
23249
|
+
await new Promise((resolve9) => setTimeout(resolve9, pollInterval));
|
|
23250
23250
|
options?.signal?.throwIfAborted();
|
|
23251
23251
|
}
|
|
23252
23252
|
} catch (error2) {
|
|
@@ -23263,7 +23263,7 @@ var init_protocol = __esm({
|
|
|
23263
23263
|
*/
|
|
23264
23264
|
request(request, resultSchema, options) {
|
|
23265
23265
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
23266
|
-
return new Promise((
|
|
23266
|
+
return new Promise((resolve9, reject) => {
|
|
23267
23267
|
const earlyReject = (error2) => {
|
|
23268
23268
|
reject(error2);
|
|
23269
23269
|
};
|
|
@@ -23341,7 +23341,7 @@ var init_protocol = __esm({
|
|
|
23341
23341
|
if (!parseResult.success) {
|
|
23342
23342
|
reject(parseResult.error);
|
|
23343
23343
|
} else {
|
|
23344
|
-
|
|
23344
|
+
resolve9(parseResult.data);
|
|
23345
23345
|
}
|
|
23346
23346
|
} catch (error2) {
|
|
23347
23347
|
reject(error2);
|
|
@@ -23602,12 +23602,12 @@ var init_protocol = __esm({
|
|
|
23602
23602
|
}
|
|
23603
23603
|
} catch {
|
|
23604
23604
|
}
|
|
23605
|
-
return new Promise((
|
|
23605
|
+
return new Promise((resolve9, reject) => {
|
|
23606
23606
|
if (signal.aborted) {
|
|
23607
23607
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
23608
23608
|
return;
|
|
23609
23609
|
}
|
|
23610
|
-
const timeoutId = setTimeout(
|
|
23610
|
+
const timeoutId = setTimeout(resolve9, interval);
|
|
23611
23611
|
signal.addEventListener("abort", () => {
|
|
23612
23612
|
clearTimeout(timeoutId);
|
|
23613
23613
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -26634,7 +26634,7 @@ var require_compile = __commonJS({
|
|
|
26634
26634
|
const schOrFunc = root.refs[ref];
|
|
26635
26635
|
if (schOrFunc)
|
|
26636
26636
|
return schOrFunc;
|
|
26637
|
-
let _sch =
|
|
26637
|
+
let _sch = resolve9.call(this, root, ref);
|
|
26638
26638
|
if (_sch === void 0) {
|
|
26639
26639
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
26640
26640
|
const { schemaId } = this.opts;
|
|
@@ -26661,7 +26661,7 @@ var require_compile = __commonJS({
|
|
|
26661
26661
|
function sameSchemaEnv(s1, s2) {
|
|
26662
26662
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
26663
26663
|
}
|
|
26664
|
-
function
|
|
26664
|
+
function resolve9(root, ref) {
|
|
26665
26665
|
let sch;
|
|
26666
26666
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
26667
26667
|
ref = sch;
|
|
@@ -27236,7 +27236,7 @@ var require_fast_uri = __commonJS({
|
|
|
27236
27236
|
}
|
|
27237
27237
|
return uri;
|
|
27238
27238
|
}
|
|
27239
|
-
function
|
|
27239
|
+
function resolve9(baseURI, relativeURI, options) {
|
|
27240
27240
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
27241
27241
|
const resolved = resolveComponent(parse5(baseURI, schemelessOptions), parse5(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
27242
27242
|
schemelessOptions.skipEscape = true;
|
|
@@ -27463,7 +27463,7 @@ var require_fast_uri = __commonJS({
|
|
|
27463
27463
|
var fastUri = {
|
|
27464
27464
|
SCHEMES,
|
|
27465
27465
|
normalize: normalize2,
|
|
27466
|
-
resolve:
|
|
27466
|
+
resolve: resolve9,
|
|
27467
27467
|
resolveComponent,
|
|
27468
27468
|
equal,
|
|
27469
27469
|
serialize,
|
|
@@ -33635,21 +33635,21 @@ var require_react_development = __commonJS({
|
|
|
33635
33635
|
);
|
|
33636
33636
|
actScopeDepth = prevActScopeDepth;
|
|
33637
33637
|
}
|
|
33638
|
-
function recursivelyFlushAsyncActWork(returnValue,
|
|
33638
|
+
function recursivelyFlushAsyncActWork(returnValue, resolve9, reject) {
|
|
33639
33639
|
var queue = ReactSharedInternals.actQueue;
|
|
33640
33640
|
if (null !== queue)
|
|
33641
33641
|
if (0 !== queue.length)
|
|
33642
33642
|
try {
|
|
33643
33643
|
flushActQueue(queue);
|
|
33644
33644
|
enqueueTask(function() {
|
|
33645
|
-
return recursivelyFlushAsyncActWork(returnValue,
|
|
33645
|
+
return recursivelyFlushAsyncActWork(returnValue, resolve9, reject);
|
|
33646
33646
|
});
|
|
33647
33647
|
return;
|
|
33648
33648
|
} catch (error2) {
|
|
33649
33649
|
ReactSharedInternals.thrownErrors.push(error2);
|
|
33650
33650
|
}
|
|
33651
33651
|
else ReactSharedInternals.actQueue = null;
|
|
33652
|
-
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) :
|
|
33652
|
+
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve9(returnValue);
|
|
33653
33653
|
}
|
|
33654
33654
|
function flushActQueue(queue) {
|
|
33655
33655
|
if (!isFlushing) {
|
|
@@ -33836,7 +33836,7 @@ var require_react_development = __commonJS({
|
|
|
33836
33836
|
));
|
|
33837
33837
|
});
|
|
33838
33838
|
return {
|
|
33839
|
-
then: function(
|
|
33839
|
+
then: function(resolve9, reject) {
|
|
33840
33840
|
didAwaitActCall = true;
|
|
33841
33841
|
thenable.then(
|
|
33842
33842
|
function(returnValue) {
|
|
@@ -33846,7 +33846,7 @@ var require_react_development = __commonJS({
|
|
|
33846
33846
|
flushActQueue(queue), enqueueTask(function() {
|
|
33847
33847
|
return recursivelyFlushAsyncActWork(
|
|
33848
33848
|
returnValue,
|
|
33849
|
-
|
|
33849
|
+
resolve9,
|
|
33850
33850
|
reject
|
|
33851
33851
|
);
|
|
33852
33852
|
});
|
|
@@ -33860,7 +33860,7 @@ var require_react_development = __commonJS({
|
|
|
33860
33860
|
ReactSharedInternals.thrownErrors.length = 0;
|
|
33861
33861
|
reject(_thrownError);
|
|
33862
33862
|
}
|
|
33863
|
-
} else
|
|
33863
|
+
} else resolve9(returnValue);
|
|
33864
33864
|
},
|
|
33865
33865
|
function(error2) {
|
|
33866
33866
|
popActScope(prevActQueue, prevActScopeDepth);
|
|
@@ -33882,15 +33882,15 @@ var require_react_development = __commonJS({
|
|
|
33882
33882
|
if (0 < ReactSharedInternals.thrownErrors.length)
|
|
33883
33883
|
throw callback = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, callback;
|
|
33884
33884
|
return {
|
|
33885
|
-
then: function(
|
|
33885
|
+
then: function(resolve9, reject) {
|
|
33886
33886
|
didAwaitActCall = true;
|
|
33887
33887
|
0 === prevActScopeDepth ? (ReactSharedInternals.actQueue = queue, enqueueTask(function() {
|
|
33888
33888
|
return recursivelyFlushAsyncActWork(
|
|
33889
33889
|
returnValue$jscomp$0,
|
|
33890
|
-
|
|
33890
|
+
resolve9,
|
|
33891
33891
|
reject
|
|
33892
33892
|
);
|
|
33893
|
-
})) :
|
|
33893
|
+
})) : resolve9(returnValue$jscomp$0);
|
|
33894
33894
|
}
|
|
33895
33895
|
};
|
|
33896
33896
|
};
|
|
@@ -44853,6 +44853,19 @@ var init_CHANGELOG = __esm({
|
|
|
44853
44853
|
"mac-app"
|
|
44854
44854
|
]
|
|
44855
44855
|
},
|
|
44856
|
+
{
|
|
44857
|
+
id: "2026-11-11-per-instance-agent-discovery",
|
|
44858
|
+
version: "undefined",
|
|
44859
|
+
date: "2026-11-11",
|
|
44860
|
+
category: "fix",
|
|
44861
|
+
title: "Agents no longer drive the wrong vcad.app window",
|
|
44862
|
+
summary: "Each vcad.app instance registers its own discovery file; clients pick one via VCAD_APP_PID/URL/DOCUMENT, every bridge result names its window, and a relaunch is reported.",
|
|
44863
|
+
features: [
|
|
44864
|
+
"agent-bridge",
|
|
44865
|
+
"mcp",
|
|
44866
|
+
"mac-app"
|
|
44867
|
+
]
|
|
44868
|
+
},
|
|
44856
44869
|
{
|
|
44857
44870
|
id: "2026-11-11-one-click-drawings",
|
|
44858
44871
|
version: "0.11.0",
|
|
@@ -44932,6 +44945,19 @@ var init_CHANGELOG = __esm({
|
|
|
44932
44945
|
"history"
|
|
44933
44946
|
]
|
|
44934
44947
|
},
|
|
44948
|
+
{
|
|
44949
|
+
id: "2026-11-11-fusion-model-edges",
|
|
44950
|
+
version: "1.0.0",
|
|
44951
|
+
date: "2026-11-11",
|
|
44952
|
+
category: "feat",
|
|
44953
|
+
title: "Model edges drawn like Fusion 360",
|
|
44954
|
+
summary: "The Mac app now outlines every B-rep face boundary, tangent fillet edges included, and draws outlines on assembly instances too. Mesh-only parts keep crease edges.",
|
|
44955
|
+
features: [
|
|
44956
|
+
"viewport",
|
|
44957
|
+
"edges",
|
|
44958
|
+
"assembly"
|
|
44959
|
+
]
|
|
44960
|
+
},
|
|
44935
44961
|
{
|
|
44936
44962
|
id: "2026-11-11-direct-manipulation",
|
|
44937
44963
|
version: "undefined",
|
|
@@ -57378,10 +57404,86 @@ var init_source_provenance = __esm({
|
|
|
57378
57404
|
}
|
|
57379
57405
|
});
|
|
57380
57406
|
|
|
57381
|
-
// src/app-
|
|
57382
|
-
import { readFileSync as readFileSync5 } from "node:fs";
|
|
57407
|
+
// src/app-discovery.ts
|
|
57408
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
57383
57409
|
import { homedir } from "node:os";
|
|
57384
|
-
import {
|
|
57410
|
+
import { join as join3, resolve as resolve3 } from "node:path";
|
|
57411
|
+
function isAlive(pid) {
|
|
57412
|
+
if (typeof pid !== "number" || pid <= 0) return false;
|
|
57413
|
+
try {
|
|
57414
|
+
process.kill(pid, 0);
|
|
57415
|
+
return true;
|
|
57416
|
+
} catch (e) {
|
|
57417
|
+
return e.code === "EPERM";
|
|
57418
|
+
}
|
|
57419
|
+
}
|
|
57420
|
+
function describeInstance(r) {
|
|
57421
|
+
return `pid ${r.pid} (${r.document_name ?? r.document_path ?? "no document"})`;
|
|
57422
|
+
}
|
|
57423
|
+
function listInstances({ home = homedir(), alive = isAlive } = {}) {
|
|
57424
|
+
const root = join3(home, ".vcad");
|
|
57425
|
+
const read = (p) => {
|
|
57426
|
+
try {
|
|
57427
|
+
return JSON.parse(readFileSync5(p, "utf8"));
|
|
57428
|
+
} catch {
|
|
57429
|
+
return null;
|
|
57430
|
+
}
|
|
57431
|
+
};
|
|
57432
|
+
let records = [];
|
|
57433
|
+
try {
|
|
57434
|
+
const dir = join3(root, "instances");
|
|
57435
|
+
records = readdirSync2(dir).filter((f) => f.endsWith(".json")).map((f) => read(join3(dir, f))).filter((r) => r !== null);
|
|
57436
|
+
} catch {
|
|
57437
|
+
}
|
|
57438
|
+
if (records.length === 0) {
|
|
57439
|
+
const legacy = read(join3(root, "app.json"));
|
|
57440
|
+
if (legacy) records = [legacy];
|
|
57441
|
+
}
|
|
57442
|
+
return records.filter((r) => alive(r.pid)).sort((a, b) => String(b.started ?? "").localeCompare(String(a.started ?? "")));
|
|
57443
|
+
}
|
|
57444
|
+
function selectInstance({
|
|
57445
|
+
env = process.env,
|
|
57446
|
+
instances,
|
|
57447
|
+
documentPath
|
|
57448
|
+
}) {
|
|
57449
|
+
if (env.VCAD_APP_URL) {
|
|
57450
|
+
const url = env.VCAD_APP_URL;
|
|
57451
|
+
return { url, instance: instances.find((r) => urlOf(r) === url) ?? null };
|
|
57452
|
+
}
|
|
57453
|
+
if (env.VCAD_APP_PID) {
|
|
57454
|
+
const pid = Number(env.VCAD_APP_PID);
|
|
57455
|
+
const instance2 = instances.find((r) => r.pid === pid);
|
|
57456
|
+
if (!instance2) {
|
|
57457
|
+
const others2 = instances.length ? ` Running: ${instances.map(describeInstance).join(", ")}.` : "";
|
|
57458
|
+
return { error: `VCAD_APP_PID=${env.VCAD_APP_PID}: no running vcad.app with that pid.${others2}` };
|
|
57459
|
+
}
|
|
57460
|
+
return { url: urlOf(instance2), instance: instance2 };
|
|
57461
|
+
}
|
|
57462
|
+
if (instances.length === 0) return { error: "no running vcad.app found (~/.vcad/instances is empty)" };
|
|
57463
|
+
const wanted = documentPath ?? env.VCAD_APP_DOCUMENT;
|
|
57464
|
+
if (wanted) {
|
|
57465
|
+
const abs = resolve3(wanted);
|
|
57466
|
+
const instance2 = instances.find((r) => r.document_path && resolve3(r.document_path) === abs);
|
|
57467
|
+
if (instance2) return { url: urlOf(instance2), instance: instance2 };
|
|
57468
|
+
}
|
|
57469
|
+
const [instance, ...others] = instances;
|
|
57470
|
+
if (!others.length) return { url: urlOf(instance), instance };
|
|
57471
|
+
return {
|
|
57472
|
+
url: urlOf(instance),
|
|
57473
|
+
instance,
|
|
57474
|
+
warning: `${instances.length} vcad.app instances are running; using the newest, ${describeInstance(instance)}. Others: ${others.map(describeInstance).join(", ")}. Set VCAD_APP_PID to choose.`
|
|
57475
|
+
};
|
|
57476
|
+
}
|
|
57477
|
+
var urlOf;
|
|
57478
|
+
var init_app_discovery = __esm({
|
|
57479
|
+
"src/app-discovery.ts"() {
|
|
57480
|
+
"use strict";
|
|
57481
|
+
urlOf = (r) => r.url ?? `http://127.0.0.1:${r.port}/mcp`;
|
|
57482
|
+
}
|
|
57483
|
+
});
|
|
57484
|
+
|
|
57485
|
+
// src/app-link.ts
|
|
57486
|
+
import { dirname, isAbsolute as isAbsolute4 } from "node:path";
|
|
57385
57487
|
function noteDocumentFolder(documentId, folder) {
|
|
57386
57488
|
folders.set(documentId, folder);
|
|
57387
57489
|
}
|
|
@@ -57393,13 +57495,27 @@ function documentFolder(documentId, document) {
|
|
|
57393
57495
|
}
|
|
57394
57496
|
function endpoint() {
|
|
57395
57497
|
if (process.env.VCAD_APP === "0") return null;
|
|
57396
|
-
|
|
57397
|
-
|
|
57398
|
-
|
|
57399
|
-
return info.url ?? `http://127.0.0.1:${info.port}/mcp`;
|
|
57400
|
-
} catch {
|
|
57401
|
-
return null;
|
|
57498
|
+
const instances = listInstances();
|
|
57499
|
+
if (pinned && (process.env.VCAD_APP_URL || instances.some((r) => r.pid === pinned?.instance?.pid))) {
|
|
57500
|
+
return pinned.url;
|
|
57402
57501
|
}
|
|
57502
|
+
const pick2 = selectInstance({ instances });
|
|
57503
|
+
if (pick2.error !== void 0) return null;
|
|
57504
|
+
if (pick2.warning && pick2.warning !== warned) {
|
|
57505
|
+
warned = pick2.warning;
|
|
57506
|
+
process.stderr.write(`[vcad-mcp] ${pick2.warning}
|
|
57507
|
+
`);
|
|
57508
|
+
}
|
|
57509
|
+
const prev = pinned?.instance;
|
|
57510
|
+
if (prev && pick2.instance && prev.instance_id !== pick2.instance.instance_id) {
|
|
57511
|
+
appChanged(prev, pick2.instance);
|
|
57512
|
+
}
|
|
57513
|
+
pinned = { url: pick2.url, instance: pick2.instance };
|
|
57514
|
+
return pick2.url;
|
|
57515
|
+
}
|
|
57516
|
+
function appChanged(prev, next) {
|
|
57517
|
+
const why = `The vcad app changed: ${describeInstance(prev)} is gone, now linked to ${describeInstance(next)} (it relaunched, or another window took over). Edits stay in this session. To show it there, call show_in_app.`;
|
|
57518
|
+
for (const id of links.keys()) loseWindow(id, why);
|
|
57403
57519
|
}
|
|
57404
57520
|
async function reconcileBeforeWrite(documentId, documents2, call = callApp) {
|
|
57405
57521
|
const link = links.get(documentId);
|
|
@@ -57613,14 +57729,17 @@ function pushPose(documentId, joints, call = callApp, now = Date.now(), base) {
|
|
|
57613
57729
|
sendPose(frame, now);
|
|
57614
57730
|
return true;
|
|
57615
57731
|
}
|
|
57616
|
-
var links, folders, callApp, PUSH_WAIT_MS, RECONCILE_WAIT_MS, wait, pushes, lateNotes, LOST_WINDOW, OPENING_TOOLS, toolDefs3, POSE_INTERVAL_MS, poseBusy, lastPose, pendingRestart, pendingLatest, poseTimer;
|
|
57732
|
+
var links, folders, pinned, warned, callApp, PUSH_WAIT_MS, RECONCILE_WAIT_MS, wait, pushes, lateNotes, LOST_WINDOW, OPENING_TOOLS, toolDefs3, POSE_INTERVAL_MS, poseBusy, lastPose, pendingRestart, pendingLatest, poseTimer;
|
|
57617
57733
|
var init_app_link = __esm({
|
|
57618
57734
|
"src/app-link.ts"() {
|
|
57619
57735
|
"use strict";
|
|
57736
|
+
init_app_discovery();
|
|
57620
57737
|
init_session_core();
|
|
57621
57738
|
init_tool_def();
|
|
57622
57739
|
links = /* @__PURE__ */ new Map();
|
|
57623
57740
|
folders = /* @__PURE__ */ new Map();
|
|
57741
|
+
pinned = null;
|
|
57742
|
+
warned = "";
|
|
57624
57743
|
callApp = async (tool, args) => {
|
|
57625
57744
|
const url = endpoint();
|
|
57626
57745
|
if (!url) return null;
|
|
@@ -57690,7 +57809,7 @@ var init_app_link = __esm({
|
|
|
57690
57809
|
|
|
57691
57810
|
// src/tools/session.ts
|
|
57692
57811
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync6 } from "node:fs";
|
|
57693
|
-
import { dirname as dirname2, resolve as
|
|
57812
|
+
import { dirname as dirname2, resolve as resolve4 } from "node:path";
|
|
57694
57813
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
57695
57814
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
57696
57815
|
function durabilityWarning() {
|
|
@@ -57762,7 +57881,7 @@ function openDocument(args) {
|
|
|
57762
57881
|
};
|
|
57763
57882
|
}
|
|
57764
57883
|
function writeLocalSnapshot(id, json) {
|
|
57765
|
-
const dir =
|
|
57884
|
+
const dir = resolve4(stateRoot(), "get_document");
|
|
57766
57885
|
mkdirSync2(dir, { recursive: true });
|
|
57767
57886
|
const path = resolveWithinRoot(`${id}.vcad`, dir);
|
|
57768
57887
|
writeFileSync2(path, json);
|
|
@@ -57975,7 +58094,7 @@ async function loadDocumentFromPath(path, store, engine) {
|
|
|
57975
58094
|
"`path` loads are local/stdio only \u2014 this server's filesystem is ephemeral. Pass the source inline to create_cad_loon, or save with save_document and reopen by `name`."
|
|
57976
58095
|
);
|
|
57977
58096
|
}
|
|
57978
|
-
const abs =
|
|
58097
|
+
const abs = resolve4(path);
|
|
57979
58098
|
let raw;
|
|
57980
58099
|
try {
|
|
57981
58100
|
raw = readFileSync6(abs, "utf8");
|
|
@@ -61780,8 +61899,8 @@ async function openBridge(createServer2, clientInfo, clientCapabilities, hooks)
|
|
|
61780
61899
|
await server.connect(serverSide);
|
|
61781
61900
|
const rpc = (method, params) => {
|
|
61782
61901
|
const id = nextId3++;
|
|
61783
|
-
return new Promise((
|
|
61784
|
-
pending.set(id, (m) =>
|
|
61902
|
+
return new Promise((resolve9) => {
|
|
61903
|
+
pending.set(id, (m) => resolve9(m));
|
|
61785
61904
|
void clientSide.send({
|
|
61786
61905
|
jsonrpc: "2.0",
|
|
61787
61906
|
id,
|
|
@@ -62118,8 +62237,8 @@ function taskElicitation(bridge, reqParams) {
|
|
|
62118
62237
|
method: "elicitation/create",
|
|
62119
62238
|
params: cleanParams
|
|
62120
62239
|
};
|
|
62121
|
-
return new Promise((
|
|
62122
|
-
record2.pendingInputs.set(key3,
|
|
62240
|
+
return new Promise((resolve9) => {
|
|
62241
|
+
record2.pendingInputs.set(key3, resolve9);
|
|
62123
62242
|
touchTask(record2, "input_required", "waiting for client input");
|
|
62124
62243
|
});
|
|
62125
62244
|
}
|
|
@@ -62144,11 +62263,11 @@ function handleTaskMethod(id, method, params) {
|
|
|
62144
62263
|
if (method === "tasks/update") {
|
|
62145
62264
|
const responses = params.inputResponses && typeof params.inputResponses === "object" ? params.inputResponses : {};
|
|
62146
62265
|
for (const [key3, response] of Object.entries(responses)) {
|
|
62147
|
-
const
|
|
62148
|
-
if (!
|
|
62266
|
+
const resolve9 = record2.pendingInputs.get(key3);
|
|
62267
|
+
if (!resolve9) continue;
|
|
62149
62268
|
record2.pendingInputs.delete(key3);
|
|
62150
62269
|
delete record2.inputRequests[key3];
|
|
62151
|
-
|
|
62270
|
+
resolve9(response);
|
|
62152
62271
|
}
|
|
62153
62272
|
if (record2.status === "input_required" && Object.keys(record2.inputRequests).length === 0) {
|
|
62154
62273
|
touchTask(record2, "working", `running ${record2.toolName}`);
|
|
@@ -62160,10 +62279,10 @@ function handleTaskMethod(id, method, params) {
|
|
|
62160
62279
|
}
|
|
62161
62280
|
record2.cancelRequested = true;
|
|
62162
62281
|
if (record2.status === "working" || record2.status === "input_required") {
|
|
62163
|
-
for (const [key3,
|
|
62282
|
+
for (const [key3, resolve9] of record2.pendingInputs) {
|
|
62164
62283
|
record2.pendingInputs.delete(key3);
|
|
62165
62284
|
delete record2.inputRequests[key3];
|
|
62166
|
-
|
|
62285
|
+
resolve9({ action: "cancel" });
|
|
62167
62286
|
}
|
|
62168
62287
|
touchTask(record2, "cancelled", "cancelled by client");
|
|
62169
62288
|
}
|
|
@@ -62841,7 +62960,7 @@ function normalizeOp(op, index) {
|
|
|
62841
62960
|
return { name, args };
|
|
62842
62961
|
}
|
|
62843
62962
|
function resolveSymbolicRefs(args, createdIds, index) {
|
|
62844
|
-
const
|
|
62963
|
+
const resolve9 = (v) => {
|
|
62845
62964
|
if (typeof v !== "string") return v;
|
|
62846
62965
|
const m = SYMBOLIC_REF.exec(v);
|
|
62847
62966
|
if (!m) return v;
|
|
@@ -62861,15 +62980,15 @@ function resolveSymbolicRefs(args, createdIds, index) {
|
|
|
62861
62980
|
};
|
|
62862
62981
|
const out = { ...args };
|
|
62863
62982
|
for (const key3 of ["part_id", "node_id"]) {
|
|
62864
|
-
if (key3 in out) out[key3] =
|
|
62983
|
+
if (key3 in out) out[key3] = resolve9(out[key3]);
|
|
62865
62984
|
}
|
|
62866
62985
|
if (out.params && typeof out.params === "object" && !Array.isArray(out.params)) {
|
|
62867
62986
|
const params = { ...out.params };
|
|
62868
62987
|
for (const key3 of ["child", "left", "right", "sketch"]) {
|
|
62869
|
-
if (key3 in params) params[key3] =
|
|
62988
|
+
if (key3 in params) params[key3] = resolve9(params[key3]);
|
|
62870
62989
|
}
|
|
62871
62990
|
if (Array.isArray(params.sketches)) {
|
|
62872
|
-
params.sketches = params.sketches.map(
|
|
62991
|
+
params.sketches = params.sketches.map(resolve9);
|
|
62873
62992
|
}
|
|
62874
62993
|
out.params = params;
|
|
62875
62994
|
}
|
|
@@ -67532,7 +67651,7 @@ async function flattenSchematic(sheet, netlister) {
|
|
|
67532
67651
|
if (def.body.hierarchy) {
|
|
67533
67652
|
err9(`Sheet '${def.name}' body has its own hierarchy \u2014 nest sheets with \`instances\` instead (ignored)`);
|
|
67534
67653
|
}
|
|
67535
|
-
const
|
|
67654
|
+
const resolve9 = (name) => {
|
|
67536
67655
|
if (ports.has(name)) {
|
|
67537
67656
|
const bound = binding.get(name);
|
|
67538
67657
|
if (bound !== void 0) return bound;
|
|
@@ -67560,7 +67679,7 @@ async function flattenSchematic(sheet, netlister) {
|
|
|
67560
67679
|
if (pins.length === 0) continue;
|
|
67561
67680
|
if (isAutoName(name) && pins.length < 2) continue;
|
|
67562
67681
|
usedNames.add(name);
|
|
67563
|
-
const flat =
|
|
67682
|
+
const flat = resolve9(name);
|
|
67564
67683
|
if (!ports.has(name) && !globals.has(name) && rootNames.has(flat)) {
|
|
67565
67684
|
err9(
|
|
67566
67685
|
`Net scope collision: local net '${name}' of sheet instance '${path}' flattens to '${flat}', which the root sheet also uses`
|
|
@@ -67584,9 +67703,9 @@ async function flattenSchematic(sheet, netlister) {
|
|
|
67584
67703
|
warn(`Hierarchical port '${port}' of sheet '${def.name}' connects to nothing inside the sheet`);
|
|
67585
67704
|
}
|
|
67586
67705
|
}
|
|
67587
|
-
for (const flag of def.body.power_flags ?? []) outFlags.push({ ...flag, net:
|
|
67706
|
+
for (const flag of def.body.power_flags ?? []) outFlags.push({ ...flag, net: resolve9(flag.net) });
|
|
67588
67707
|
instances.push({ path, sheet: def.name, refs });
|
|
67589
|
-
await elaborateAll(def.instances ?? [], path, offset,
|
|
67708
|
+
await elaborateAll(def.instances ?? [], path, offset, resolve9, stack);
|
|
67590
67709
|
};
|
|
67591
67710
|
await elaborateAll(h.instances ?? [], "", { x: 0, y: 0 }, (n) => n, []);
|
|
67592
67711
|
const nets = {};
|
|
@@ -69141,12 +69260,12 @@ var init_enclosure = __esm({
|
|
|
69141
69260
|
// src/wasm/ecad-diff.ts
|
|
69142
69261
|
import { createRequire } from "node:module";
|
|
69143
69262
|
import { fileURLToPath } from "node:url";
|
|
69144
|
-
import { dirname as dirname3, resolve as
|
|
69263
|
+
import { dirname as dirname3, resolve as resolve5 } from "node:path";
|
|
69145
69264
|
function load() {
|
|
69146
69265
|
if (cached2 !== void 0) return cached2;
|
|
69147
69266
|
try {
|
|
69148
69267
|
const here = dirname3(fileURLToPath(import.meta.url));
|
|
69149
|
-
const pkg =
|
|
69268
|
+
const pkg = resolve5(here, "../../../../crates/vcad-ecad-diff-wasm/pkg/vcad_ecad_diff_wasm.js");
|
|
69150
69269
|
const req = createRequire(import.meta.url);
|
|
69151
69270
|
cached2 = req(pkg);
|
|
69152
69271
|
} catch {
|
|
@@ -83028,7 +83147,7 @@ import { execFile } from "child_process";
|
|
|
83028
83147
|
import {
|
|
83029
83148
|
existsSync as existsSync4,
|
|
83030
83149
|
mkdtempSync as mkdtempSync2,
|
|
83031
|
-
readdirSync as
|
|
83150
|
+
readdirSync as readdirSync3,
|
|
83032
83151
|
readFileSync as readFileSync8,
|
|
83033
83152
|
rmSync,
|
|
83034
83153
|
writeFileSync as writeFileSync5
|
|
@@ -83086,7 +83205,7 @@ function listEvalTasks(args) {
|
|
|
83086
83205
|
const tasksDir = join6(mechevalRoot, "tasks");
|
|
83087
83206
|
const suiteFilter = args.suite ? String(args.suite).toUpperCase() : null;
|
|
83088
83207
|
const tasks2 = [];
|
|
83089
|
-
for (const file of
|
|
83208
|
+
for (const file of readdirSync3(tasksDir).sort()) {
|
|
83090
83209
|
if (!file.endsWith(".json")) continue;
|
|
83091
83210
|
try {
|
|
83092
83211
|
const raw = JSON.parse(readFileSync8(join6(tasksDir, file), "utf8"));
|
|
@@ -87474,14 +87593,14 @@ var init_acoustics = __esm({
|
|
|
87474
87593
|
// src/tools/import.ts
|
|
87475
87594
|
import { createHash as createHash6 } from "node:crypto";
|
|
87476
87595
|
import { readFileSync as readFileSync9, existsSync as existsSync5, statSync as statSync2, mkdirSync as mkdirSync3, writeFileSync as writeFileSync7 } from "node:fs";
|
|
87477
|
-
import { basename, join as join7, resolve as
|
|
87596
|
+
import { basename, join as join7, resolve as resolve6, sep as sep3 } from "node:path";
|
|
87478
87597
|
function exportRoot() {
|
|
87479
87598
|
return process.env.VCAD_MCP_EXPORT_DIR ?? process.cwd();
|
|
87480
87599
|
}
|
|
87481
87600
|
function isWithinExportRoot(path) {
|
|
87482
87601
|
if (path.includes("\0")) return false;
|
|
87483
|
-
const root =
|
|
87484
|
-
const abs =
|
|
87602
|
+
const root = resolve6(exportRoot());
|
|
87603
|
+
const abs = resolve6(path);
|
|
87485
87604
|
return abs === root || abs.startsWith(root + sep3);
|
|
87486
87605
|
}
|
|
87487
87606
|
function stepNodePath(bytes, diskPath, label) {
|
|
@@ -87492,7 +87611,7 @@ function stepNodePath(bytes, diskPath, label) {
|
|
|
87492
87611
|
mkdirSync3(dir, { recursive: true });
|
|
87493
87612
|
const file = join7(dir, `${digest}.step`);
|
|
87494
87613
|
if (!existsSync5(file)) writeFileSync7(file, bytes);
|
|
87495
|
-
return { path:
|
|
87614
|
+
return { path: resolve6(file), portable: true };
|
|
87496
87615
|
} catch {
|
|
87497
87616
|
return { path: `step:${digest}/${label}`, portable: false };
|
|
87498
87617
|
}
|
|
@@ -87568,7 +87687,7 @@ function readStepInput(input) {
|
|
|
87568
87687
|
if (stat.size > MAX_STEP_BYTES) {
|
|
87569
87688
|
throw new Error(`STEP file exceeds ${MAX_STEP_BYTES} byte limit`);
|
|
87570
87689
|
}
|
|
87571
|
-
return { bytes: readFileSync9(filepath), diskPath:
|
|
87690
|
+
return { bytes: readFileSync9(filepath), diskPath: resolve6(filepath) };
|
|
87572
87691
|
}
|
|
87573
87692
|
function skippedFaceSummary(report, warnings) {
|
|
87574
87693
|
const skipped = report.reduce((sum, s) => sum + s.skipped_faces.length, 0);
|
|
@@ -87741,11 +87860,11 @@ var init_import = __esm({
|
|
|
87741
87860
|
|
|
87742
87861
|
// src/tools/import-urdf.ts
|
|
87743
87862
|
import { readFileSync as readFileSync10, existsSync as existsSync6, statSync as statSync3 } from "node:fs";
|
|
87744
|
-
import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute5, resolve as
|
|
87863
|
+
import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute5, resolve as resolve7, sep as sep4 } from "node:path";
|
|
87745
87864
|
function resolveMeshPath(filename, urdfDir, packageRoots, confineRoot) {
|
|
87746
87865
|
const confined = (p) => {
|
|
87747
|
-
const abs =
|
|
87748
|
-
const root =
|
|
87866
|
+
const abs = resolve7(p);
|
|
87867
|
+
const root = resolve7(confineRoot);
|
|
87749
87868
|
const rootSep = root.endsWith(sep4) ? root : root + sep4;
|
|
87750
87869
|
if (abs !== root && !abs.startsWith(rootSep)) return null;
|
|
87751
87870
|
return existsSync6(abs) && statSync3(abs).isFile() ? abs : null;
|
|
@@ -87754,14 +87873,14 @@ function resolveMeshPath(filename, urdfDir, packageRoots, confineRoot) {
|
|
|
87754
87873
|
const pkgMatch = filename.match(/^package:\/\/([^/]+)\/?(.*)$/);
|
|
87755
87874
|
if (pkgMatch) {
|
|
87756
87875
|
for (const root of packageRoots) {
|
|
87757
|
-
const hit = confined(
|
|
87876
|
+
const hit = confined(resolve7(root, pkgMatch[1], pkgMatch[2]));
|
|
87758
87877
|
if (hit) return hit;
|
|
87759
87878
|
}
|
|
87760
87879
|
return null;
|
|
87761
87880
|
}
|
|
87762
87881
|
const stripped = filename.startsWith("file://") ? filename.slice("file://".length) : filename;
|
|
87763
87882
|
if (isAbsolute5(stripped)) return confined(stripped);
|
|
87764
|
-
if (urdfDir) return confined(
|
|
87883
|
+
if (urdfDir) return confined(resolve7(urdfDir, stripped));
|
|
87765
87884
|
return null;
|
|
87766
87885
|
}
|
|
87767
87886
|
function inlineMeshImports2(doc, engine, urdfDir, packageRoots, confineRoot) {
|
|
@@ -91004,13 +91123,13 @@ ${issues.map((i) => i.problem).join("\n")}`
|
|
|
91004
91123
|
}
|
|
91005
91124
|
async function hasFfmpeg() {
|
|
91006
91125
|
if (ffmpegAvailable !== null) return ffmpegAvailable;
|
|
91007
|
-
ffmpegAvailable = await new Promise((
|
|
91126
|
+
ffmpegAvailable = await new Promise((resolve9) => {
|
|
91008
91127
|
try {
|
|
91009
91128
|
const p = spawn("ffmpeg", ["-version"], { stdio: "ignore" });
|
|
91010
|
-
p.on("error", () =>
|
|
91011
|
-
p.on("exit", (code) =>
|
|
91129
|
+
p.on("error", () => resolve9(false));
|
|
91130
|
+
p.on("exit", (code) => resolve9(code === 0));
|
|
91012
91131
|
} catch {
|
|
91013
|
-
|
|
91132
|
+
resolve9(false);
|
|
91014
91133
|
}
|
|
91015
91134
|
});
|
|
91016
91135
|
return ffmpegAvailable;
|
|
@@ -91049,13 +91168,13 @@ function startMp4Encoder(width, height, fps) {
|
|
|
91049
91168
|
const exitError = (code) => new Error(
|
|
91050
91169
|
`ffmpeg exited ${code}: ${Buffer.concat(errChunks).toString().slice(-400)}`
|
|
91051
91170
|
);
|
|
91052
|
-
const done = new Promise((
|
|
91171
|
+
const done = new Promise((resolve9, reject) => {
|
|
91053
91172
|
p.on("error", (e) => {
|
|
91054
91173
|
failure2 = e;
|
|
91055
91174
|
reject(e);
|
|
91056
91175
|
});
|
|
91057
91176
|
p.on("close", (code) => {
|
|
91058
|
-
if (code === 0)
|
|
91177
|
+
if (code === 0) resolve9(Buffer.concat(out));
|
|
91059
91178
|
else {
|
|
91060
91179
|
failure2 ??= exitError(code);
|
|
91061
91180
|
reject(failure2);
|
|
@@ -91066,15 +91185,15 @@ function startMp4Encoder(width, height, fps) {
|
|
|
91066
91185
|
});
|
|
91067
91186
|
return {
|
|
91068
91187
|
writeFrame(rgba) {
|
|
91069
|
-
return new Promise((
|
|
91188
|
+
return new Promise((resolve9, reject) => {
|
|
91070
91189
|
if (failure2) return reject(failure2);
|
|
91071
91190
|
if (p.exitCode !== null || p.stdin.destroyed) {
|
|
91072
91191
|
return reject(failure2 ?? exitError(p.exitCode));
|
|
91073
91192
|
}
|
|
91074
|
-
if (p.stdin.write(rgba)) return
|
|
91193
|
+
if (p.stdin.write(rgba)) return resolve9();
|
|
91075
91194
|
const onDrain = () => {
|
|
91076
91195
|
p.removeListener("close", onClose);
|
|
91077
|
-
|
|
91196
|
+
resolve9();
|
|
91078
91197
|
};
|
|
91079
91198
|
const onClose = () => {
|
|
91080
91199
|
p.stdin.removeListener("drain", onDrain);
|
|
@@ -92634,8 +92753,8 @@ var init_server3 = __esm({
|
|
|
92634
92753
|
resolveLoonAssets(doc, { base_dir }, engine);
|
|
92635
92754
|
});
|
|
92636
92755
|
PKG_VERSION = (() => {
|
|
92637
|
-
if ("0.11.0-main.
|
|
92638
|
-
return "0.11.0-main.
|
|
92756
|
+
if ("0.11.0-main.163") {
|
|
92757
|
+
return "0.11.0-main.163";
|
|
92639
92758
|
}
|
|
92640
92759
|
try {
|
|
92641
92760
|
const req = createRequire3(import.meta.url);
|
|
@@ -92644,8 +92763,8 @@ var init_server3 = __esm({
|
|
|
92644
92763
|
return "0.0.0";
|
|
92645
92764
|
}
|
|
92646
92765
|
})();
|
|
92647
|
-
BUILD_SHA = "
|
|
92648
|
-
BUILD_TIME = "2026-11-
|
|
92766
|
+
BUILD_SHA = "816ee12b085c12b403a35ebfedb6c276e175a3af";
|
|
92767
|
+
BUILD_TIME = "2026-11-11T21:40:44.212Z";
|
|
92649
92768
|
SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
|
|
92650
92769
|
VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
|
|
92651
92770
|
INSTANCE_ID = randomUUID5().slice(0, 8);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vcad/mcp",
|
|
3
|
-
"version": "0.11.0-main.
|
|
3
|
+
"version": "0.11.0-main.163",
|
|
4
4
|
"description": "vcad MCP server — parametric CAD + PCB design tools for AI agents (self-contained: bundled server + kernel WASM)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"homepage": "https://github.com/muni-works/vcad",
|
|
21
21
|
"vcadBuild": {
|
|
22
|
-
"sha": "
|
|
23
|
-
"builtAt": "2026-11-
|
|
22
|
+
"sha": "816ee12b085c12b403a35ebfedb6c276e175a3af",
|
|
23
|
+
"builtAt": "2026-11-11T21:40:44.212Z"
|
|
24
24
|
}
|
|
25
25
|
}
|
package/skill/SKILL.md
CHANGED
|
@@ -81,6 +81,28 @@ Call `server_info` first.
|
|
|
81
81
|
Tell the user and suggest restarting their agent (or updating vcad.app).
|
|
82
82
|
- `durable: false` → sessions won't survive a restart; keep the loon source.
|
|
83
83
|
|
|
84
|
+
## More than one vcad.app
|
|
85
|
+
|
|
86
|
+
Each running vcad.app registers itself in `~/.vcad/instances/<pid>.json`
|
|
87
|
+
(pid, port, open document, launch time); `~/.vcad/app.json` only points at
|
|
88
|
+
the newest. Every app-bridge result ends with `[vcad.app pid N · document]`
|
|
89
|
+
and carries `_meta["io.vcad/instance"]`: check it names the window you mean.
|
|
90
|
+
A `⚠ vcad.app CHANGED` notice means the app relaunched or another window took
|
|
91
|
+
over — re-check the open document before trusting earlier state.
|
|
92
|
+
|
|
93
|
+
Pick the window explicitly when more than one runs:
|
|
94
|
+
|
|
95
|
+
- `VCAD_APP_PID=<pid>` — that instance; fails loudly if it's gone.
|
|
96
|
+
- `VCAD_APP_URL=http://127.0.0.1:<port>/mcp` — that endpoint, verbatim.
|
|
97
|
+
- `VCAD_APP_DOCUMENT=<path>` — the instance with that file open.
|
|
98
|
+
- otherwise the newest, with a warning listing the others. The choice is
|
|
99
|
+
pinned for the client's lifetime; a later launch never steals it.
|
|
100
|
+
- `VCAD_APP=0` — `@vcad/mcp` doesn't link to any app.
|
|
101
|
+
|
|
102
|
+
**Never `pkill`/`killall` vcad.app by pattern.** Other sessions may be driving
|
|
103
|
+
other windows, and to them it looks like a crash. Quit only an instance you
|
|
104
|
+
launched, by its pid (`kill <pid>`, from `~/.vcad/instances/`).
|
|
105
|
+
|
|
84
106
|
## Ground rules
|
|
85
107
|
|
|
86
108
|
- vcad has no hosted services. Never send the user to a website to view,
|