@vcad/mcp 0.9.4-main.6 → 0.9.4-main.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/index.mjs +157 -130
- package/package.json +3 -3
- package/vcad_kernel_wasm_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -6,4 +6,4 @@ vcad's MCP server as a self-contained bundle (server + BRep kernel WASM).
|
|
|
6
6
|
{ "mcpServers": { "vcad": { "command": "npx", "args": ["-y", "@vcad/mcp"] } } }
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
Built from
|
|
9
|
+
Built from f09f3d656a04f8a18840c42116208ada180ce487 at 2026-07-24T16:11:19.940Z. Source: https://github.com/ecto/vcad
|
package/index.mjs
CHANGED
|
@@ -538,6 +538,7 @@ __export(vcad_kernel_wasm_exports, {
|
|
|
538
538
|
camGenerateRoughing3d: () => camGenerateRoughing3d,
|
|
539
539
|
camGetDefaultTools: () => camGetDefaultTools,
|
|
540
540
|
camToolpathStats: () => camToolpathStats,
|
|
541
|
+
checkDesignConstraints: () => checkDesignConstraints,
|
|
541
542
|
checkPrintability: () => checkPrintability,
|
|
542
543
|
checkSheetMetal: () => checkSheetMetal,
|
|
543
544
|
circuitAcResponse: () => circuitAcResponse,
|
|
@@ -688,6 +689,7 @@ __export(vcad_kernel_wasm_exports, {
|
|
|
688
689
|
sliceMesh: () => sliceMesh,
|
|
689
690
|
sliceMeshWithProgress: () => sliceMeshWithProgress,
|
|
690
691
|
sliceSolid: () => sliceSolid,
|
|
692
|
+
solveDesignConstraints: () => solveDesignConstraints,
|
|
691
693
|
solveForwardKinematics: () => solveForwardKinematics,
|
|
692
694
|
solveSketchSegments: () => solveSketchSegments,
|
|
693
695
|
textBounds: () => textBounds,
|
|
@@ -1139,6 +1141,27 @@ function camToolpathStats(toolpath_json) {
|
|
|
1139
1141
|
}
|
|
1140
1142
|
return takeFromExternrefTable0(ret[0]);
|
|
1141
1143
|
}
|
|
1144
|
+
function checkDesignConstraints(doc_json) {
|
|
1145
|
+
let deferred3_0;
|
|
1146
|
+
let deferred3_1;
|
|
1147
|
+
try {
|
|
1148
|
+
const ptr0 = passStringToWasm0(doc_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
1149
|
+
const len0 = WASM_VECTOR_LEN;
|
|
1150
|
+
const ret = wasm.checkDesignConstraints(ptr0, len0);
|
|
1151
|
+
var ptr2 = ret[0];
|
|
1152
|
+
var len2 = ret[1];
|
|
1153
|
+
if (ret[3]) {
|
|
1154
|
+
ptr2 = 0;
|
|
1155
|
+
len2 = 0;
|
|
1156
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
1157
|
+
}
|
|
1158
|
+
deferred3_0 = ptr2;
|
|
1159
|
+
deferred3_1 = len2;
|
|
1160
|
+
return getStringFromWasm0(ptr2, len2);
|
|
1161
|
+
} finally {
|
|
1162
|
+
wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1142
1165
|
function checkPrintability(solid, printer_profile) {
|
|
1143
1166
|
_assertClass(solid, Solid);
|
|
1144
1167
|
const ptr0 = passStringToWasm0(printer_profile, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
@@ -2986,6 +3009,29 @@ function sliceSolid(solid, settings, segments) {
|
|
|
2986
3009
|
}
|
|
2987
3010
|
return SliceResult.__wrap(ret[0]);
|
|
2988
3011
|
}
|
|
3012
|
+
function solveDesignConstraints(doc_json, options_json) {
|
|
3013
|
+
let deferred4_0;
|
|
3014
|
+
let deferred4_1;
|
|
3015
|
+
try {
|
|
3016
|
+
const ptr0 = passStringToWasm0(doc_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
3017
|
+
const len0 = WASM_VECTOR_LEN;
|
|
3018
|
+
const ptr1 = passStringToWasm0(options_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
3019
|
+
const len1 = WASM_VECTOR_LEN;
|
|
3020
|
+
const ret = wasm.solveDesignConstraints(ptr0, len0, ptr1, len1);
|
|
3021
|
+
var ptr3 = ret[0];
|
|
3022
|
+
var len3 = ret[1];
|
|
3023
|
+
if (ret[3]) {
|
|
3024
|
+
ptr3 = 0;
|
|
3025
|
+
len3 = 0;
|
|
3026
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
3027
|
+
}
|
|
3028
|
+
deferred4_0 = ptr3;
|
|
3029
|
+
deferred4_1 = len3;
|
|
3030
|
+
return getStringFromWasm0(ptr3, len3);
|
|
3031
|
+
} finally {
|
|
3032
|
+
wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
2989
3035
|
function solveForwardKinematics(doc_json) {
|
|
2990
3036
|
const ptr0 = passStringToWasm0(doc_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
2991
3037
|
const len0 = WASM_VECTOR_LEN;
|
|
@@ -10031,120 +10077,22 @@ var init_diff = __esm({
|
|
|
10031
10077
|
});
|
|
10032
10078
|
|
|
10033
10079
|
// ../engine/dist/sequence.js
|
|
10034
|
-
function
|
|
10035
|
-
const
|
|
10036
|
-
if (
|
|
10037
|
-
|
|
10038
|
-
const first = keys[0];
|
|
10039
|
-
if (t2 <= first.t)
|
|
10040
|
-
return first.value;
|
|
10041
|
-
const last = keys[keys.length - 1];
|
|
10042
|
-
if (t2 >= last.t)
|
|
10043
|
-
return last.value;
|
|
10044
|
-
const idx = keys.findIndex((k) => k.t > t2);
|
|
10045
|
-
const a = keys[idx - 1];
|
|
10046
|
-
const b = keys[idx];
|
|
10047
|
-
const span = b.t - a.t;
|
|
10048
|
-
let u = span <= 0 ? 1 : (t2 - a.t) / span;
|
|
10049
|
-
switch (b.ease ?? "linear") {
|
|
10050
|
-
case "step":
|
|
10051
|
-
u = u >= 1 ? 1 : 0;
|
|
10052
|
-
break;
|
|
10053
|
-
case "ease-in-out":
|
|
10054
|
-
u = u * u * (3 - 2 * u);
|
|
10055
|
-
break;
|
|
10056
|
-
default:
|
|
10057
|
-
break;
|
|
10058
|
-
}
|
|
10059
|
-
return a.value + (b.value - a.value) * u;
|
|
10060
|
-
}
|
|
10061
|
-
function cameraPoseAt(shots, t2, prevPose) {
|
|
10062
|
-
let active;
|
|
10063
|
-
for (const shot of shots) {
|
|
10064
|
-
if (t2 >= shot.startS && t2 < shot.endS)
|
|
10065
|
-
active = shot;
|
|
10066
|
-
}
|
|
10067
|
-
if (!active)
|
|
10068
|
-
return prevPose;
|
|
10069
|
-
const span = active.endS - active.startS;
|
|
10070
|
-
const u = span <= 0 ? 1 : (t2 - active.startS) / span;
|
|
10071
|
-
const kind = active.kind;
|
|
10072
|
-
switch (kind.type) {
|
|
10073
|
-
case "Turntable":
|
|
10074
|
-
return {
|
|
10075
|
-
azimuthDeg: kind.degrees * u,
|
|
10076
|
-
elevationDeg: kind.elevationDeg,
|
|
10077
|
-
dolly: 1
|
|
10078
|
-
};
|
|
10079
|
-
case "Orbit":
|
|
10080
|
-
return {
|
|
10081
|
-
azimuthDeg: kind.from[0] + (kind.to[0] - kind.from[0]) * u,
|
|
10082
|
-
elevationDeg: kind.from[1] + (kind.to[1] - kind.from[1]) * u,
|
|
10083
|
-
dolly: 1
|
|
10084
|
-
};
|
|
10085
|
-
case "Focus":
|
|
10086
|
-
return {
|
|
10087
|
-
azimuthDeg: prevPose.azimuthDeg,
|
|
10088
|
-
elevationDeg: prevPose.elevationDeg,
|
|
10089
|
-
dolly: 1 + (kind.dolly - 1) * u,
|
|
10090
|
-
target: kind.target
|
|
10091
|
-
};
|
|
10092
|
-
case "Static":
|
|
10093
|
-
return { ...DEFAULT_POSE };
|
|
10080
|
+
function requireWasm() {
|
|
10081
|
+
const mod = getKernelWasmSync();
|
|
10082
|
+
if (!mod || typeof mod.sample_timeline_sequence !== "function" || typeof mod.sample_timeline_track !== "function") {
|
|
10083
|
+
throw new Error("kernel WASM not initialized (or too old for timeline sampling) \u2014 await getKernelWasm() before sampling sequences");
|
|
10094
10084
|
}
|
|
10085
|
+
return mod;
|
|
10086
|
+
}
|
|
10087
|
+
function sampleTrackValue(track, t2) {
|
|
10088
|
+
return requireWasm().sample_timeline_track(JSON.stringify(track), t2);
|
|
10095
10089
|
}
|
|
10096
10090
|
function sampleSequence(doc, timelineOverride) {
|
|
10097
10091
|
const timeline = timelineOverride ?? doc.timeline;
|
|
10098
10092
|
if (!timeline)
|
|
10099
10093
|
return [];
|
|
10100
|
-
const
|
|
10101
|
-
|
|
10102
|
-
const tracks = timeline.tracks ?? [];
|
|
10103
|
-
const shots = timeline.camera ?? [];
|
|
10104
|
-
const hasParamTracks2 = tracks.some((tr) => tr.target.type === "Parameter");
|
|
10105
|
-
const frames = [];
|
|
10106
|
-
let prevParams;
|
|
10107
|
-
let prevPose = { ...DEFAULT_POSE };
|
|
10108
|
-
for (let index = 0; index < frameCount; index++) {
|
|
10109
|
-
const t2 = index / fps;
|
|
10110
|
-
const params = {};
|
|
10111
|
-
const joints = {};
|
|
10112
|
-
const visibility = {};
|
|
10113
|
-
let explode = 0;
|
|
10114
|
-
for (const track of tracks) {
|
|
10115
|
-
const value = sampleTrackValue(track, t2);
|
|
10116
|
-
const target = track.target;
|
|
10117
|
-
switch (target.type) {
|
|
10118
|
-
case "Parameter":
|
|
10119
|
-
params[target.name] = value;
|
|
10120
|
-
break;
|
|
10121
|
-
case "Joint":
|
|
10122
|
-
joints[target.jointId] = value;
|
|
10123
|
-
break;
|
|
10124
|
-
case "Visibility":
|
|
10125
|
-
visibility[target.instanceId] = value > 0.5;
|
|
10126
|
-
break;
|
|
10127
|
-
case "Explode":
|
|
10128
|
-
explode = value;
|
|
10129
|
-
break;
|
|
10130
|
-
}
|
|
10131
|
-
}
|
|
10132
|
-
const camera = cameraPoseAt(shots, t2, prevPose);
|
|
10133
|
-
prevPose = camera;
|
|
10134
|
-
const geometryDirty = prevParams === void 0 ? hasParamTracks2 : Object.keys(params).some((name) => params[name] !== prevParams[name]);
|
|
10135
|
-
prevParams = params;
|
|
10136
|
-
frames.push({
|
|
10137
|
-
index,
|
|
10138
|
-
t: t2,
|
|
10139
|
-
params,
|
|
10140
|
-
joints,
|
|
10141
|
-
visibility,
|
|
10142
|
-
explode,
|
|
10143
|
-
camera,
|
|
10144
|
-
geometryDirty
|
|
10145
|
-
});
|
|
10146
|
-
}
|
|
10147
|
-
return frames;
|
|
10094
|
+
const json = requireWasm().sample_timeline_sequence(JSON.stringify(timeline));
|
|
10095
|
+
return JSON.parse(json);
|
|
10148
10096
|
}
|
|
10149
10097
|
function poseDocument(doc, frame) {
|
|
10150
10098
|
const posed = structuredClone(doc);
|
|
@@ -10166,11 +10114,10 @@ function poseDocument(doc, frame) {
|
|
|
10166
10114
|
}
|
|
10167
10115
|
return posed;
|
|
10168
10116
|
}
|
|
10169
|
-
var DEFAULT_POSE;
|
|
10170
10117
|
var init_sequence = __esm({
|
|
10171
10118
|
"../engine/dist/sequence.js"() {
|
|
10172
10119
|
"use strict";
|
|
10173
|
-
|
|
10120
|
+
init_wasm_singleton();
|
|
10174
10121
|
}
|
|
10175
10122
|
});
|
|
10176
10123
|
|
|
@@ -10211,7 +10158,7 @@ async function isEcadAvailable2() {
|
|
|
10211
10158
|
const wasm2 = await loadEcadWasm();
|
|
10212
10159
|
return wasm2 !== null;
|
|
10213
10160
|
}
|
|
10214
|
-
async function
|
|
10161
|
+
async function solveDesignConstraints2(doc, options) {
|
|
10215
10162
|
return verifyWithKernel("design constraints", (wasm2) => {
|
|
10216
10163
|
if (typeof wasm2.solveDesignConstraints !== "function") {
|
|
10217
10164
|
throw new Error("kernel WASM predates solveDesignConstraints");
|
|
@@ -10219,7 +10166,7 @@ async function solveDesignConstraints(doc, options) {
|
|
|
10219
10166
|
return JSON.parse(wasm2.solveDesignConstraints(JSON.stringify(doc), JSON.stringify(options ?? {})));
|
|
10220
10167
|
});
|
|
10221
10168
|
}
|
|
10222
|
-
async function
|
|
10169
|
+
async function checkDesignConstraints2(doc) {
|
|
10223
10170
|
return verifyWithKernel("design constraints (check)", (wasm2) => {
|
|
10224
10171
|
if (typeof wasm2.checkDesignConstraints !== "function") {
|
|
10225
10172
|
throw new Error("kernel WASM predates checkDesignConstraints");
|
|
@@ -11885,7 +11832,7 @@ __export(dist_exports, {
|
|
|
11885
11832
|
buildPartDocument: () => buildPartDocument,
|
|
11886
11833
|
buildReceipt: () => buildReceipt,
|
|
11887
11834
|
builtinSymbols: () => builtinSymbols,
|
|
11888
|
-
checkDesignConstraints: () =>
|
|
11835
|
+
checkDesignConstraints: () => checkDesignConstraints2,
|
|
11889
11836
|
checkEnclosureFit: () => checkEnclosureFit,
|
|
11890
11837
|
checkErc: () => checkErc,
|
|
11891
11838
|
circuitAcResponse: () => circuitAcResponse2,
|
|
@@ -11976,7 +11923,7 @@ __export(dist_exports, {
|
|
|
11976
11923
|
searchParts: () => searchParts,
|
|
11977
11924
|
semanticDiff: () => semanticDiff,
|
|
11978
11925
|
semanticDiffFallback: () => semanticDiffFallback,
|
|
11979
|
-
solveDesignConstraints: () =>
|
|
11926
|
+
solveDesignConstraints: () => solveDesignConstraints2,
|
|
11980
11927
|
solveForwardKinematics: () => solveForwardKinematics2,
|
|
11981
11928
|
threeWayMerge: () => threeWayMerge,
|
|
11982
11929
|
toWorld: () => toWorld,
|
|
@@ -41634,6 +41581,20 @@ var init_CHANGELOG = __esm({
|
|
|
41634
41581
|
"route_nets"
|
|
41635
41582
|
]
|
|
41636
41583
|
},
|
|
41584
|
+
{
|
|
41585
|
+
id: "2026-07-23-render-view-triangle-guard",
|
|
41586
|
+
version: "0.9.4",
|
|
41587
|
+
date: "2026-07-23",
|
|
41588
|
+
category: "fix",
|
|
41589
|
+
title: "render_view refuses over-dense documents instead of crashing",
|
|
41590
|
+
summary: "Documents tessellating past 120k triangles (e.g. large sphere patterns) now get an actionable error from render_view instead of OOM-killing the server with a >100 MB per-triangle SVG.",
|
|
41591
|
+
features: [
|
|
41592
|
+
"render"
|
|
41593
|
+
],
|
|
41594
|
+
mcpTools: [
|
|
41595
|
+
"render_view"
|
|
41596
|
+
]
|
|
41597
|
+
},
|
|
41637
41598
|
{
|
|
41638
41599
|
id: "2026-07-23-plane-stitch-maze-rescue",
|
|
41639
41600
|
version: "0.9.4",
|
|
@@ -48462,6 +48423,7 @@ function undoLastSnapshot(documentId) {
|
|
|
48462
48423
|
function clearHistory(documentId) {
|
|
48463
48424
|
sessionHistory.delete(documentId);
|
|
48464
48425
|
lastChangedParts.delete(documentId);
|
|
48426
|
+
lastTriangleCount.delete(documentId);
|
|
48465
48427
|
}
|
|
48466
48428
|
function recordLastChanged(documentId, partIds) {
|
|
48467
48429
|
if (!documentId) return;
|
|
@@ -48470,7 +48432,14 @@ function recordLastChanged(documentId, partIds) {
|
|
|
48470
48432
|
function getLastChanged(documentId) {
|
|
48471
48433
|
return lastChangedParts.get(documentId) ?? null;
|
|
48472
48434
|
}
|
|
48473
|
-
|
|
48435
|
+
function recordTriangles(documentId, triangles) {
|
|
48436
|
+
if (!documentId) return;
|
|
48437
|
+
lastTriangleCount.set(documentId, triangles);
|
|
48438
|
+
}
|
|
48439
|
+
function getLastTriangles(documentId) {
|
|
48440
|
+
return lastTriangleCount.get(documentId) ?? null;
|
|
48441
|
+
}
|
|
48442
|
+
var fallbackDocuments, scopeProvider, documents, nextId, MAX_HISTORY, sessionHistory, lastChangedParts, lastTriangleCount;
|
|
48474
48443
|
var init_session_core = __esm({
|
|
48475
48444
|
"src/tools/session-core.ts"() {
|
|
48476
48445
|
"use strict";
|
|
@@ -48490,6 +48459,7 @@ var init_session_core = __esm({
|
|
|
48490
48459
|
MAX_HISTORY = 50;
|
|
48491
48460
|
sessionHistory = /* @__PURE__ */ new Map();
|
|
48492
48461
|
lastChangedParts = /* @__PURE__ */ new Map();
|
|
48462
|
+
lastTriangleCount = /* @__PURE__ */ new Map();
|
|
48493
48463
|
}
|
|
48494
48464
|
});
|
|
48495
48465
|
|
|
@@ -49682,7 +49652,10 @@ var init_loon = __esm({
|
|
|
49682
49652
|
if (doc) {
|
|
49683
49653
|
if (targetId) documents.set(targetId, doc);
|
|
49684
49654
|
const integrity = computeIntegrity(doc, ctx.engine);
|
|
49685
|
-
if (integrity)
|
|
49655
|
+
if (integrity) {
|
|
49656
|
+
appendIntegrity(result, integrity);
|
|
49657
|
+
if (targetId) recordTriangles(targetId, integrity.triangles);
|
|
49658
|
+
}
|
|
49686
49659
|
}
|
|
49687
49660
|
} catch {
|
|
49688
49661
|
}
|
|
@@ -51570,7 +51543,10 @@ function dispatchRegistryTool(toolName, args, engine) {
|
|
|
51570
51543
|
]);
|
|
51571
51544
|
if (engine) {
|
|
51572
51545
|
const integrity = computeIntegrity(doc, engine);
|
|
51573
|
-
if (integrity)
|
|
51546
|
+
if (integrity) {
|
|
51547
|
+
appendIntegrity(result, integrity);
|
|
51548
|
+
recordTriangles(documentId, integrity.triangles);
|
|
51549
|
+
}
|
|
51574
51550
|
}
|
|
51575
51551
|
}
|
|
51576
51552
|
return result;
|
|
@@ -53224,7 +53200,10 @@ function applyEdits(args, engine) {
|
|
|
53224
53200
|
]);
|
|
53225
53201
|
if (engine) {
|
|
53226
53202
|
const integrity = computeIntegrity(working, engine);
|
|
53227
|
-
if (integrity)
|
|
53203
|
+
if (integrity) {
|
|
53204
|
+
appendIntegrity(result, integrity);
|
|
53205
|
+
recordTriangles(documentId, integrity.triangles);
|
|
53206
|
+
}
|
|
53228
53207
|
}
|
|
53229
53208
|
}
|
|
53230
53209
|
return result;
|
|
@@ -57223,7 +57202,7 @@ async function setParameters(input, engine) {
|
|
|
57223
57202
|
}
|
|
57224
57203
|
let constraintSolve;
|
|
57225
57204
|
if ((doc.constraints ?? []).length > 0) {
|
|
57226
|
-
const outcome = await
|
|
57205
|
+
const outcome = await solveDesignConstraints2(doc);
|
|
57227
57206
|
if (outcome.status === "ok") {
|
|
57228
57207
|
doc.nodes = outcome.value.document.nodes;
|
|
57229
57208
|
doc.constraints = outcome.value.document.constraints;
|
|
@@ -57240,7 +57219,10 @@ async function setParameters(input, engine) {
|
|
|
57240
57219
|
});
|
|
57241
57220
|
result.structuredContent = { changed };
|
|
57242
57221
|
const integrity = computeIntegrity(doc, engine);
|
|
57243
|
-
if (integrity)
|
|
57222
|
+
if (integrity) {
|
|
57223
|
+
appendIntegrity(result, integrity);
|
|
57224
|
+
recordTriangles(documentId, integrity.triangles);
|
|
57225
|
+
}
|
|
57244
57226
|
return result;
|
|
57245
57227
|
}
|
|
57246
57228
|
function parameterGradient(input, engine) {
|
|
@@ -57363,7 +57345,7 @@ function describe(c) {
|
|
|
57363
57345
|
async function constraintReceiptClaims(doc) {
|
|
57364
57346
|
const constraints = doc.constraints ?? [];
|
|
57365
57347
|
if (constraints.length === 0) return [];
|
|
57366
|
-
const outcome = await
|
|
57348
|
+
const outcome = await checkDesignConstraints2(doc);
|
|
57367
57349
|
const byId = /* @__PURE__ */ new Map();
|
|
57368
57350
|
if (outcome.status === "ok") {
|
|
57369
57351
|
for (const r of outcome.value.residuals) byId.set(r.id, r);
|
|
@@ -57440,7 +57422,7 @@ function worst(statuses) {
|
|
|
57440
57422
|
}
|
|
57441
57423
|
async function verifyConstraintClaims(doc, receipt) {
|
|
57442
57424
|
const checks = [];
|
|
57443
|
-
const outcome = await
|
|
57425
|
+
const outcome = await checkDesignConstraints2(doc);
|
|
57444
57426
|
const byId = /* @__PURE__ */ new Map();
|
|
57445
57427
|
if (outcome.status === "ok") {
|
|
57446
57428
|
for (const r of outcome.value.residuals) byId.set(r.id, r);
|
|
@@ -67961,7 +67943,7 @@ async function placementDrcIfMoved(doc, report) {
|
|
|
67961
67943
|
return pcb ? await summarizePlacementDrc(pcb) : void 0;
|
|
67962
67944
|
}
|
|
67963
67945
|
async function solveAndReport(doc, documentId) {
|
|
67964
|
-
const outcome = await
|
|
67946
|
+
const outcome = await solveDesignConstraints2(doc);
|
|
67965
67947
|
if (outcome.status !== "ok") {
|
|
67966
67948
|
return err6(`constraint solve unavailable: ${outcome.reason}`);
|
|
67967
67949
|
}
|
|
@@ -68087,7 +68069,7 @@ async function listConstraints(args) {
|
|
|
68087
68069
|
hint: "add_constraint persists solver-enforced geometric relationships"
|
|
68088
68070
|
});
|
|
68089
68071
|
}
|
|
68090
|
-
const outcome = await
|
|
68072
|
+
const outcome = await checkDesignConstraints2(ctx.doc);
|
|
68091
68073
|
const report = outcome.status === "ok" ? outcome.value : void 0;
|
|
68092
68074
|
const residuals = new Map(report?.residuals.map((r) => [r.id, r.residual]) ?? []);
|
|
68093
68075
|
const measured = new Map(report?.drivenValues.map((d) => [d.id, d.value]) ?? []);
|
|
@@ -68614,6 +68596,13 @@ function complexityGuard(doc) {
|
|
|
68614
68596
|
return null;
|
|
68615
68597
|
}
|
|
68616
68598
|
async function rasterize(svg, widthPx, background = "white") {
|
|
68599
|
+
const svgBytes = Buffer.byteLength(svg, "utf8");
|
|
68600
|
+
if (svgBytes > MAX_RASTER_SVG_BYTES) {
|
|
68601
|
+
return {
|
|
68602
|
+
png: null,
|
|
68603
|
+
reason: `rasterization refused: SVG is ${svgBytes} bytes (cap ${MAX_RASTER_SVG_BYTES}) \u2014 the document is too dense to raster safely`
|
|
68604
|
+
};
|
|
68605
|
+
}
|
|
68617
68606
|
let ResvgCtor;
|
|
68618
68607
|
try {
|
|
68619
68608
|
({ Resvg: ResvgCtor } = await import("@resvg/resvg-js"));
|
|
@@ -68648,6 +68637,22 @@ async function renderView(args) {
|
|
|
68648
68637
|
2048,
|
|
68649
68638
|
Math.max(64, Number.isFinite(widthRaw) ? Math.round(widthRaw) : DEFAULT_WIDTH_PX)
|
|
68650
68639
|
);
|
|
68640
|
+
const knownTriangles = documentId ? getLastTriangles(documentId) : null;
|
|
68641
|
+
if (knownTriangles !== null && knownTriangles > MAX_RENDER_TRIANGLES) {
|
|
68642
|
+
return {
|
|
68643
|
+
content: [
|
|
68644
|
+
{
|
|
68645
|
+
type: "text",
|
|
68646
|
+
text: JSON.stringify({
|
|
68647
|
+
error: `render refused: document tessellates to ${knownTriangles} triangles (render limit ${MAX_RENDER_TRIANGLES})`,
|
|
68648
|
+
document_id: documentId,
|
|
68649
|
+
hint: "The renderer emits per-triangle SVG, so documents this dense exhaust memory. Reduce pattern counts / sphere counts, render a subset via `focus`, or inspect numerically via inspect_cad / measure. For full geometry use export_cad."
|
|
68650
|
+
})
|
|
68651
|
+
}
|
|
68652
|
+
],
|
|
68653
|
+
isError: true
|
|
68654
|
+
};
|
|
68655
|
+
}
|
|
68651
68656
|
const tooComplex = complexityGuard(doc);
|
|
68652
68657
|
if (tooComplex) {
|
|
68653
68658
|
return {
|
|
@@ -68901,8 +68906,25 @@ async function renderView(args) {
|
|
|
68901
68906
|
]
|
|
68902
68907
|
}, [asset]);
|
|
68903
68908
|
}
|
|
68904
|
-
const note = raster.reason === "module-missing" ? "Install @resvg/resvg-js for PNG output; returning raw SVG." : `PNG ${raster.reason}; returning raw SVG.`;
|
|
68905
68909
|
const svgBytes = Buffer.byteLength(svg, "utf8");
|
|
68910
|
+
if (raster.reason !== "module-missing" && svgBytes > MAX_INLINE_SVG_BYTES) {
|
|
68911
|
+
return {
|
|
68912
|
+
content: [
|
|
68913
|
+
{
|
|
68914
|
+
type: "text",
|
|
68915
|
+
text: JSON.stringify({
|
|
68916
|
+
error: `render failed: ${raster.reason}`,
|
|
68917
|
+
document_id: documentId,
|
|
68918
|
+
view: viewLabel,
|
|
68919
|
+
svg_bytes: svgBytes,
|
|
68920
|
+
hint: "The document is too dense for the per-triangle SVG renderer. Reduce pattern counts, render a subset via `focus`, or inspect numerically via inspect_cad / measure. For full geometry use export_cad."
|
|
68921
|
+
})
|
|
68922
|
+
}
|
|
68923
|
+
],
|
|
68924
|
+
isError: true
|
|
68925
|
+
};
|
|
68926
|
+
}
|
|
68927
|
+
const note = raster.reason === "module-missing" ? "Install @resvg/resvg-js for PNG output; returning raw SVG." : `PNG ${raster.reason}; returning raw SVG.`;
|
|
68906
68928
|
return {
|
|
68907
68929
|
content: [
|
|
68908
68930
|
{
|
|
@@ -69307,7 +69329,7 @@ async function renderStackup(args) {
|
|
|
69307
69329
|
});
|
|
69308
69330
|
return withRenderAssets({ content }, assets);
|
|
69309
69331
|
}
|
|
69310
|
-
var renderViewSchema, SVG_SCALE, DEFAULT_WIDTH_PX, MAX_NODES, MAX_PATTERN_INSTANCES, MAX_INLINE_SVG_BYTES, renderPcbSchema, PCB_MARGIN_MM, RATSNEST_COLOR, renderRatsnestSchema, COPPER_LAYERS2, renderStackupSchema, toolDefs23;
|
|
69332
|
+
var renderViewSchema, SVG_SCALE, DEFAULT_WIDTH_PX, MAX_NODES, MAX_PATTERN_INSTANCES, MAX_RENDER_TRIANGLES, MAX_RASTER_SVG_BYTES, MAX_INLINE_SVG_BYTES, renderPcbSchema, PCB_MARGIN_MM, RATSNEST_COLOR, renderRatsnestSchema, COPPER_LAYERS2, renderStackupSchema, toolDefs23;
|
|
69311
69333
|
var init_render2 = __esm({
|
|
69312
69334
|
"src/tools/render.ts"() {
|
|
69313
69335
|
"use strict";
|
|
@@ -69386,6 +69408,8 @@ var init_render2 = __esm({
|
|
|
69386
69408
|
DEFAULT_WIDTH_PX = 800;
|
|
69387
69409
|
MAX_NODES = 1e4;
|
|
69388
69410
|
MAX_PATTERN_INSTANCES = 5e4;
|
|
69411
|
+
MAX_RENDER_TRIANGLES = 12e4;
|
|
69412
|
+
MAX_RASTER_SVG_BYTES = 64 * 1024 * 1024;
|
|
69389
69413
|
MAX_INLINE_SVG_BYTES = 256 * 1024;
|
|
69390
69414
|
renderPcbSchema = {
|
|
69391
69415
|
type: "object",
|
|
@@ -77060,6 +77084,7 @@ ${issues.map((i) => i.track >= 0 ? `track[${i.track}]: ${i.problem}` : i.problem
|
|
|
77060
77084
|
);
|
|
77061
77085
|
}
|
|
77062
77086
|
doc.timeline = timeline;
|
|
77087
|
+
await getKernelWasm();
|
|
77063
77088
|
const frames = sampleSequence(doc);
|
|
77064
77089
|
return ok({
|
|
77065
77090
|
duration_s: timeline.durationS,
|
|
@@ -77330,6 +77355,7 @@ async function renderSequence(args, ctx) {
|
|
|
77330
77355
|
${issues.map((i) => i.problem).join("\n")}`
|
|
77331
77356
|
);
|
|
77332
77357
|
}
|
|
77358
|
+
await getKernelWasm();
|
|
77333
77359
|
const frames = sampleSequence(doc, timeline);
|
|
77334
77360
|
if (frames.length > MAX_FRAMES) {
|
|
77335
77361
|
return err2(
|
|
@@ -77514,6 +77540,7 @@ async function exportVideo(args, ctx) {
|
|
|
77514
77540
|
return err2(`timeline invalid:
|
|
77515
77541
|
${issues.map((i) => i.problem).join("\n")}`);
|
|
77516
77542
|
}
|
|
77543
|
+
await getKernelWasm();
|
|
77517
77544
|
const frames = sampleSequence(doc, timeline);
|
|
77518
77545
|
if (frames.length > MAX_FRAMES) {
|
|
77519
77546
|
return err2(
|
|
@@ -78780,8 +78807,8 @@ var init_server3 = __esm({
|
|
|
78780
78807
|
init_order_feed();
|
|
78781
78808
|
init_animate();
|
|
78782
78809
|
PKG_VERSION = (() => {
|
|
78783
|
-
if ("0.9.4-main.
|
|
78784
|
-
return "0.9.4-main.
|
|
78810
|
+
if ("0.9.4-main.8") {
|
|
78811
|
+
return "0.9.4-main.8";
|
|
78785
78812
|
}
|
|
78786
78813
|
try {
|
|
78787
78814
|
const req = createRequire2(import.meta.url);
|
|
@@ -78790,8 +78817,8 @@ var init_server3 = __esm({
|
|
|
78790
78817
|
return "0.0.0";
|
|
78791
78818
|
}
|
|
78792
78819
|
})();
|
|
78793
|
-
BUILD_SHA = "
|
|
78794
|
-
BUILD_TIME = "2026-07-
|
|
78820
|
+
BUILD_SHA = "f09f3d656a04f8a18840c42116208ada180ce487";
|
|
78821
|
+
BUILD_TIME = "2026-07-24T16:11:19.940Z";
|
|
78795
78822
|
SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
|
|
78796
78823
|
VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
|
|
78797
78824
|
INSTANCE_ID = randomUUID6().slice(0, 8);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vcad/mcp",
|
|
3
|
-
"version": "0.9.4-main.
|
|
3
|
+
"version": "0.9.4-main.8",
|
|
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://vcad.io",
|
|
21
21
|
"vcadBuild": {
|
|
22
|
-
"sha": "
|
|
23
|
-
"builtAt": "2026-07-
|
|
22
|
+
"sha": "f09f3d656a04f8a18840c42116208ada180ce487",
|
|
23
|
+
"builtAt": "2026-07-24T16:11:19.940Z"
|
|
24
24
|
}
|
|
25
25
|
}
|
package/vcad_kernel_wasm_bg.wasm
CHANGED
|
Binary file
|