@vcad/mcp 0.10.0-main.113 → 0.10.0-main.114

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 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 6fe98c8bcad683e78ce3185512bd51fbfc36aa73 at 2026-10-20T22:54:39.478Z. Source: https://github.com/ecto/vcad
9
+ Built from a680346430d6b8e6acd07ec8f2821f14ccd6a05f at 2026-10-20T23:26:44.068Z. Source: https://github.com/ecto/vcad
package/index.mjs CHANGED
@@ -51399,6 +51399,64 @@ function setSessionScopeProvider(provider) {
51399
51399
  function activeDocuments() {
51400
51400
  return scopeProvider() ?? fallbackDocuments;
51401
51401
  }
51402
+ function versionsFor(map) {
51403
+ let v = writeVersions.get(map);
51404
+ if (!v) writeVersions.set(map, v = /* @__PURE__ */ new Map());
51405
+ return v;
51406
+ }
51407
+ function bumpVersion(map, id) {
51408
+ const v = versionsFor(map);
51409
+ v.set(id, (v.get(id) ?? 0) + 1);
51410
+ }
51411
+ function safeFree(engine) {
51412
+ try {
51413
+ engine.free?.();
51414
+ } catch {
51415
+ }
51416
+ }
51417
+ function dropEngineIn(map, id) {
51418
+ const cache2 = engineCaches.get(map);
51419
+ const entry = cache2?.get(id);
51420
+ if (!entry) return;
51421
+ cache2.delete(id);
51422
+ safeFree(entry.engine);
51423
+ }
51424
+ function markDocumentWritten(documentId) {
51425
+ bumpVersion(activeDocuments(), documentId);
51426
+ }
51427
+ function takeCachedEngine(documentId, doc) {
51428
+ const map = activeDocuments();
51429
+ const cache2 = engineCaches.get(map);
51430
+ const entry = cache2?.get(documentId);
51431
+ if (!entry) return null;
51432
+ cache2.delete(documentId);
51433
+ if (entry.doc === doc && map.get(documentId) === doc && entry.version === (versionsFor(map).get(documentId) ?? 0)) {
51434
+ return entry.engine;
51435
+ }
51436
+ safeFree(entry.engine);
51437
+ return null;
51438
+ }
51439
+ function storeEngine(documentId, doc, engine) {
51440
+ const map = activeDocuments();
51441
+ if (map.get(documentId) !== doc) {
51442
+ safeFree(engine);
51443
+ return;
51444
+ }
51445
+ let cache2 = engineCaches.get(map);
51446
+ if (!cache2) engineCaches.set(map, cache2 = /* @__PURE__ */ new Map());
51447
+ const prev = cache2.get(documentId);
51448
+ if (prev && prev.engine !== engine) safeFree(prev.engine);
51449
+ cache2.set(documentId, { engine, doc, version: versionsFor(map).get(documentId) ?? 0 });
51450
+ }
51451
+ function dropEngine(documentId) {
51452
+ dropEngineIn(activeDocuments(), documentId);
51453
+ }
51454
+ function freeScopeEngines(map) {
51455
+ const cache2 = engineCaches.get(map);
51456
+ if (!cache2) return;
51457
+ for (const entry of cache2.values()) safeFree(entry.engine);
51458
+ cache2.clear();
51459
+ }
51402
51460
  function randomSuffix() {
51403
51461
  const bytes = new Uint8Array(9);
51404
51462
  globalThis.crypto.getRandomValues(bytes);
@@ -51468,9 +51526,10 @@ function resolveDocInput(args, inlineKeys = ["document"]) {
51468
51526
  function cloneDoc(doc) {
51469
51527
  return JSON.parse(JSON.stringify(doc));
51470
51528
  }
51471
- function recordHistorySnapshot(documentId) {
51529
+ function recordHistorySnapshot(documentId, toolName) {
51472
51530
  const doc = documents.get(documentId);
51473
51531
  if (!doc) return;
51532
+ if (!toolName || !ENGINE_MANAGED_TOOLS.has(toolName)) markDocumentWritten(documentId);
51474
51533
  const stack = sessionHistory.get(documentId) ?? [];
51475
51534
  stack.push(cloneDoc(doc));
51476
51535
  if (stack.length > MAX_HISTORY) stack.shift();
@@ -51489,6 +51548,7 @@ function undoLastSnapshot(documentId) {
51489
51548
  }
51490
51549
  function clearHistory(documentId) {
51491
51550
  sessionHistory.delete(documentId);
51551
+ dropEngine(documentId);
51492
51552
  lastChangedParts.delete(documentId);
51493
51553
  lastTriangleCount.delete(documentId);
51494
51554
  }
@@ -51506,7 +51566,7 @@ function recordTriangles(documentId, triangles) {
51506
51566
  function getLastTriangles(documentId) {
51507
51567
  return lastTriangleCount.get(documentId) ?? null;
51508
51568
  }
51509
- var fallbackDocuments, scopeProvider, documents, nextId, BOOT_TOKEN_LEN, BOOT_TOKEN, durabilityProbe, documentEnterHooks, MAX_HISTORY, sessionHistory, lastChangedParts, lastTriangleCount;
51569
+ var fallbackDocuments, scopeProvider, documents, engineCaches, writeVersions, ENGINE_MANAGED_TOOLS, nextId, BOOT_TOKEN_LEN, BOOT_TOKEN, durabilityProbe, documentEnterHooks, MAX_HISTORY, sessionHistory, lastChangedParts, lastTriangleCount;
51510
51570
  var init_session_core = __esm({
51511
51571
  "src/tools/session-core.ts"() {
51512
51572
  "use strict";
@@ -51516,13 +51576,28 @@ var init_session_core = __esm({
51516
51576
  documents = {
51517
51577
  has: (id) => activeDocuments().has(id),
51518
51578
  get: (id) => activeDocuments().get(id),
51519
- set: (id, doc) => activeDocuments().set(id, doc),
51520
- delete: (id) => activeDocuments().delete(id),
51521
- clear: () => activeDocuments().clear(),
51579
+ set: (id, doc) => {
51580
+ const map = activeDocuments();
51581
+ bumpVersion(map, id);
51582
+ return map.set(id, doc);
51583
+ },
51584
+ delete: (id) => {
51585
+ const map = activeDocuments();
51586
+ dropEngineIn(map, id);
51587
+ return map.delete(id);
51588
+ },
51589
+ clear: () => {
51590
+ const map = activeDocuments();
51591
+ freeScopeEngines(map);
51592
+ map.clear();
51593
+ },
51522
51594
  get size() {
51523
51595
  return activeDocuments().size;
51524
51596
  }
51525
51597
  };
51598
+ engineCaches = /* @__PURE__ */ new WeakMap();
51599
+ writeVersions = /* @__PURE__ */ new WeakMap();
51600
+ ENGINE_MANAGED_TOOLS = /* @__PURE__ */ new Set(["create", "update", "delete", "set_material"]);
51526
51601
  nextId = 1;
51527
51602
  BOOT_TOKEN_LEN = 4;
51528
51603
  BOOT_TOKEN = randomSuffix().slice(0, BOOT_TOKEN_LEN);
@@ -53159,7 +53234,21 @@ function durabilityWarning() {
53159
53234
  }
53160
53235
  function runInSessionScope(user, fn) {
53161
53236
  if (!user) return fn();
53162
- return sessionScope.run({ documents: /* @__PURE__ */ new Map(), user }, fn);
53237
+ const documents2 = /* @__PURE__ */ new Map();
53238
+ const release = () => freeScopeEngines(documents2);
53239
+ let out;
53240
+ try {
53241
+ out = sessionScope.run({ documents: documents2, user }, fn);
53242
+ } catch (e) {
53243
+ release();
53244
+ throw e;
53245
+ }
53246
+ if (out && typeof out.then === "function") {
53247
+ out.then(release, release);
53248
+ } else {
53249
+ release();
53250
+ }
53251
+ return out;
53163
53252
  }
53164
53253
  function currentUser() {
53165
53254
  return sessionScope.getStore()?.user ?? null;
@@ -55810,12 +55899,14 @@ function runMutationViaEngine(toolName, toolArgs, doc, documentId) {
55810
55899
  const wasm3 = getKernelWasmSync();
55811
55900
  const factory = wasm3?.WasmDocumentEngine;
55812
55901
  if (!factory || typeof factory.withReplica !== "function") return null;
55813
- const engine = factory.withReplica(0);
55902
+ const cachedEngine = takeCachedEngine(documentId, doc);
55903
+ const engine = cachedEngine ?? factory.withReplica(0);
55904
+ let keep = false;
55814
55905
  try {
55815
55906
  if (typeof engine.apply_tool !== "function") return null;
55816
55907
  const deprecation = typeof toolArgs.part_id === "string" ? partIdDeprecation(toolArgs.part_id, rootForPartId(doc, toolArgs.part_id)) : void 0;
55817
55908
  const args = engineArgs(toolName, toolArgs, doc);
55818
- engine.import_ir(JSON.stringify(doc));
55909
+ if (!cachedEngine) engine.import_ir(JSON.stringify(doc));
55819
55910
  const envelope = JSON.parse(engine.apply_tool(toolName, JSON.stringify(args)));
55820
55911
  if (!envelope.ok || !envelope.result) {
55821
55912
  const err9 = envelope.error ?? { kind: "invalid", message: "engine returned no result" };
@@ -55832,6 +55923,8 @@ function runMutationViaEngine(toolName, toolArgs, doc, documentId) {
55832
55923
  }
55833
55924
  for (const k of Object.keys(doc)) delete doc[k];
55834
55925
  Object.assign(doc, next);
55926
+ storeEngine(documentId, doc, engine);
55927
+ keep = true;
55835
55928
  const warnings = [...envelope.result.warnings ?? [], ...deprecation ? [deprecation] : []];
55836
55929
  const payload = { document_id: documentId };
55837
55930
  if (toolName === "delete") {
@@ -55855,7 +55948,7 @@ function runMutationViaEngine(toolName, toolArgs, doc, documentId) {
55855
55948
  if (warnings.length) payload.warnings = warnings;
55856
55949
  return { content: [{ type: "text", text: JSON.stringify(payload) }] };
55857
55950
  } finally {
55858
- engine.free?.();
55951
+ if (!keep) engine.free?.();
55859
55952
  }
55860
55953
  }
55861
55954
  function runMutation(toolName, rawArgs, doc, documentId, opts = {}) {
@@ -55864,6 +55957,7 @@ function runMutation(toolName, rawArgs, doc, documentId, opts = {}) {
55864
55957
  const viaEngine = runMutationViaEngine(toolName, toolArgs, doc, documentId);
55865
55958
  if (viaEngine) return viaEngine;
55866
55959
  }
55960
+ if (documentId) markDocumentWritten(documentId);
55867
55961
  if (toolName === "delete") {
55868
55962
  const partId = String(toolArgs.part_id ?? "");
55869
55963
  if (!partId) throw new Error("delete: missing `part_id`");
@@ -56054,6 +56148,7 @@ var init_registry_dispatch = __esm({
56054
56148
  "use strict";
56055
56149
  init_dist3();
56056
56150
  init_session2();
56151
+ init_session_core();
56057
56152
  init_part_ids2();
56058
56153
  init_dist();
56059
56154
  init_pose();
@@ -87038,7 +87133,7 @@ async function createServer(existingEngine, context = { user: null }) {
87038
87133
  }
87039
87134
  }
87040
87135
  if (incomingId && name !== "undo" && def?.behavior.writesDoc && documents.has(incomingId)) {
87041
- recordHistorySnapshot(incomingId);
87136
+ recordHistorySnapshot(incomingId, name);
87042
87137
  }
87043
87138
  const runTool = async () => {
87044
87139
  if (!def) {
@@ -87396,8 +87491,8 @@ var init_server3 = __esm({
87396
87491
  init_order_feed();
87397
87492
  init_animate();
87398
87493
  PKG_VERSION = (() => {
87399
- if ("0.10.0-main.113") {
87400
- return "0.10.0-main.113";
87494
+ if ("0.10.0-main.114") {
87495
+ return "0.10.0-main.114";
87401
87496
  }
87402
87497
  try {
87403
87498
  const req = createRequire2(import.meta.url);
@@ -87406,8 +87501,8 @@ var init_server3 = __esm({
87406
87501
  return "0.0.0";
87407
87502
  }
87408
87503
  })();
87409
- BUILD_SHA = "6fe98c8bcad683e78ce3185512bd51fbfc36aa73";
87410
- BUILD_TIME = "2026-10-20T22:54:39.478Z";
87504
+ BUILD_SHA = "a680346430d6b8e6acd07ec8f2821f14ccd6a05f";
87505
+ BUILD_TIME = "2026-10-20T23:26:44.068Z";
87411
87506
  SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
87412
87507
  VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
87413
87508
  INSTANCE_ID = randomUUID7().slice(0, 8);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcad/mcp",
3
- "version": "0.10.0-main.113",
3
+ "version": "0.10.0-main.114",
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": "6fe98c8bcad683e78ce3185512bd51fbfc36aa73",
23
- "builtAt": "2026-10-20T22:54:39.478Z"
22
+ "sha": "a680346430d6b8e6acd07ec8f2821f14ccd6a05f",
23
+ "builtAt": "2026-10-20T23:26:44.068Z"
24
24
  }
25
25
  }
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/vcad_kernel_wasm_bg.wasm
3
- size: 35340760 bytes
4
- sha256: e9098257eb46c289fd8d98352eacdb6b9cb8bbc76aca2ba3db7b1bfff3d8a83a
3
+ size: 35323488 bytes
4
+ sha256: 3a4f66bfab16cafe28c6409cd71c6dedcf0a910a856e0649adcff9dce4b7db5a