@pascal-app/mcp 1.0.1 → 1.0.4

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.
Files changed (196) hide show
  1. package/README.md +47 -26
  2. package/dist/bin/pascal-mcp.js +8 -2
  3. package/dist/bridge/scene-bridge.d.ts +41 -6
  4. package/dist/bridge/scene-bridge.d.ts.map +1 -1
  5. package/dist/bridge/scene-bridge.js +230 -45
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -0
  9. package/dist/operations/scene-operations.d.ts +23 -3
  10. package/dist/operations/scene-operations.d.ts.map +1 -1
  11. package/dist/operations/scene-operations.js +31 -1
  12. package/dist/prompts/from-brief.js +1 -1
  13. package/dist/prompts/iterate-on-feedback.js +1 -1
  14. package/dist/prompts/scene-guidance.js +3 -3
  15. package/dist/resources/agent-guide.d.ts.map +1 -1
  16. package/dist/resources/agent-guide.js +22 -1
  17. package/dist/resources/catalog-items.d.ts +4 -5
  18. package/dist/resources/catalog-items.d.ts.map +1 -1
  19. package/dist/resources/catalog-items.js +7 -9
  20. package/dist/resources/design-schema.d.ts +9 -0
  21. package/dist/resources/design-schema.d.ts.map +1 -0
  22. package/dist/resources/design-schema.js +21 -0
  23. package/dist/resources/index.d.ts +3 -1
  24. package/dist/resources/index.d.ts.map +1 -1
  25. package/dist/resources/index.js +5 -2
  26. package/dist/server.d.ts +19 -0
  27. package/dist/server.d.ts.map +1 -1
  28. package/dist/server.js +14 -6
  29. package/dist/storage/disk-artifact-store.d.ts +9 -0
  30. package/dist/storage/disk-artifact-store.d.ts.map +1 -0
  31. package/dist/storage/disk-artifact-store.js +46 -0
  32. package/dist/storage/index.d.ts +1 -0
  33. package/dist/storage/index.d.ts.map +1 -1
  34. package/dist/storage/index.js +1 -0
  35. package/dist/storage/sqlite-scene-store.d.ts +2 -2
  36. package/dist/storage/sqlite-scene-store.d.ts.map +1 -1
  37. package/dist/storage/sqlite-scene-store.js +4 -3
  38. package/dist/storage/types.d.ts +32 -3
  39. package/dist/storage/types.d.ts.map +1 -1
  40. package/dist/storage/types.js +12 -0
  41. package/dist/tools/add-column.d.ts +5 -0
  42. package/dist/tools/add-column.d.ts.map +1 -0
  43. package/dist/tools/add-column.js +58 -0
  44. package/dist/tools/add-object.d.ts +60 -0
  45. package/dist/tools/add-object.d.ts.map +1 -0
  46. package/dist/tools/add-object.js +156 -0
  47. package/dist/tools/apply-patch.d.ts +3 -0
  48. package/dist/tools/apply-patch.d.ts.map +1 -1
  49. package/dist/tools/apply-patch.js +28 -2
  50. package/dist/tools/asset-catalog.d.ts +9 -5
  51. package/dist/tools/asset-catalog.d.ts.map +1 -1
  52. package/dist/tools/asset-catalog.js +10 -12
  53. package/dist/tools/check-collisions.d.ts +1 -1
  54. package/dist/tools/check-collisions.d.ts.map +1 -1
  55. package/dist/tools/check-collisions.js +1 -2
  56. package/dist/tools/clear-scene.d.ts +9 -0
  57. package/dist/tools/clear-scene.d.ts.map +1 -0
  58. package/dist/tools/clear-scene.js +59 -0
  59. package/dist/tools/collections.d.ts +4 -0
  60. package/dist/tools/collections.d.ts.map +1 -0
  61. package/dist/tools/collections.js +52 -0
  62. package/dist/tools/construction-tools.d.ts +8 -41
  63. package/dist/tools/construction-tools.d.ts.map +1 -1
  64. package/dist/tools/construction-tools.js +120 -230
  65. package/dist/tools/create-unit.d.ts +2 -0
  66. package/dist/tools/create-unit.d.ts.map +1 -1
  67. package/dist/tools/describe-node.d.ts.map +1 -1
  68. package/dist/tools/describe-node.js +8 -6
  69. package/dist/tools/errors.d.ts +11 -0
  70. package/dist/tools/errors.d.ts.map +1 -1
  71. package/dist/tools/errors.js +10 -0
  72. package/dist/tools/find-nodes.d.ts +3 -19
  73. package/dist/tools/find-nodes.d.ts.map +1 -1
  74. package/dist/tools/find-nodes.js +150 -53
  75. package/dist/tools/geometry-script-worker.d.ts +2 -0
  76. package/dist/tools/geometry-script-worker.d.ts.map +1 -0
  77. package/dist/tools/geometry-script-worker.js +21 -0
  78. package/dist/tools/get-scene.d.ts +1 -0
  79. package/dist/tools/get-scene.d.ts.map +1 -1
  80. package/dist/tools/get-scene.js +3 -1
  81. package/dist/tools/honest-patch-guard.d.ts +2 -0
  82. package/dist/tools/honest-patch-guard.d.ts.map +1 -0
  83. package/dist/tools/honest-patch-guard.js +32 -0
  84. package/dist/tools/hosted-services.d.ts +4 -0
  85. package/dist/tools/hosted-services.d.ts.map +1 -0
  86. package/dist/tools/hosted-services.js +30 -0
  87. package/dist/tools/index.d.ts +10 -1
  88. package/dist/tools/index.d.ts.map +1 -1
  89. package/dist/tools/index.js +17 -26
  90. package/dist/tools/live-sync.d.ts +24 -5
  91. package/dist/tools/live-sync.d.ts.map +1 -1
  92. package/dist/tools/live-sync.js +47 -26
  93. package/dist/tools/local-geometry-scripts.d.ts +8 -0
  94. package/dist/tools/local-geometry-scripts.d.ts.map +1 -0
  95. package/dist/tools/local-geometry-scripts.js +67 -0
  96. package/dist/tools/measure.d.ts +6 -0
  97. package/dist/tools/measure.d.ts.map +1 -1
  98. package/dist/tools/measure.js +33 -65
  99. package/dist/tools/measurement.d.ts +1 -36
  100. package/dist/tools/measurement.d.ts.map +1 -1
  101. package/dist/tools/measurement.js +2 -94
  102. package/dist/tools/node-world-point.d.ts +37 -0
  103. package/dist/tools/node-world-point.d.ts.map +1 -0
  104. package/dist/tools/node-world-point.js +457 -0
  105. package/dist/tools/normalize-schema-dialect.d.ts.map +1 -1
  106. package/dist/tools/normalize-schema-dialect.js +20 -0
  107. package/dist/tools/patch-guards.d.ts +58 -0
  108. package/dist/tools/patch-guards.d.ts.map +1 -0
  109. package/dist/tools/patch-guards.js +253 -0
  110. package/dist/tools/photo-to-scene/photo-to-scene.d.ts.map +1 -1
  111. package/dist/tools/photo-to-scene/photo-to-scene.js +3 -2
  112. package/dist/tools/place-design.d.ts +34 -0
  113. package/dist/tools/place-design.d.ts.map +1 -0
  114. package/dist/tools/place-design.js +91 -0
  115. package/dist/tools/redo.d.ts +2 -0
  116. package/dist/tools/redo.d.ts.map +1 -1
  117. package/dist/tools/redo.js +2 -2
  118. package/dist/tools/room-tools.d.ts +50 -113
  119. package/dist/tools/room-tools.d.ts.map +1 -1
  120. package/dist/tools/room-tools.js +129 -565
  121. package/dist/tools/scene-lifecycle/create-project.d.ts.map +1 -1
  122. package/dist/tools/scene-lifecycle/create-project.js +26 -1
  123. package/dist/tools/scene-lifecycle/delete-scene.d.ts +2 -0
  124. package/dist/tools/scene-lifecycle/delete-scene.d.ts.map +1 -1
  125. package/dist/tools/scene-lifecycle/delete-scene.js +4 -3
  126. package/dist/tools/scene-lifecycle/save-scene.d.ts +1 -0
  127. package/dist/tools/scene-lifecycle/save-scene.d.ts.map +1 -1
  128. package/dist/tools/scene-lifecycle/save-scene.js +46 -6
  129. package/dist/tools/scene-lifecycle/test-utils.d.ts +2 -2
  130. package/dist/tools/scene-lifecycle/test-utils.d.ts.map +1 -1
  131. package/dist/tools/scene-lifecycle/test-utils.js +2 -1
  132. package/dist/tools/set-unit-members.d.ts +2 -0
  133. package/dist/tools/set-unit-members.d.ts.map +1 -1
  134. package/dist/tools/set-zone.d.ts +2 -0
  135. package/dist/tools/set-zone.d.ts.map +1 -1
  136. package/dist/tools/set-zone.js +2 -2
  137. package/dist/tools/shared-tools.d.ts +30 -0
  138. package/dist/tools/shared-tools.d.ts.map +1 -0
  139. package/dist/tools/shared-tools.js +361 -0
  140. package/dist/tools/structure-tools.d.ts +57 -0
  141. package/dist/tools/structure-tools.d.ts.map +1 -0
  142. package/dist/tools/structure-tools.js +57 -0
  143. package/dist/tools/undo.d.ts +2 -0
  144. package/dist/tools/undo.d.ts.map +1 -1
  145. package/dist/tools/undo.js +2 -2
  146. package/dist/tools/validate-design.d.ts +136 -0
  147. package/dist/tools/validate-design.d.ts.map +1 -0
  148. package/dist/tools/validate-design.js +28 -0
  149. package/dist/tools/validate-scene.d.ts +5 -0
  150. package/dist/tools/validate-scene.d.ts.map +1 -1
  151. package/dist/tools/validate-scene.js +8 -6
  152. package/dist/tools/variants/mutations.js +1 -1
  153. package/dist/tools/view-scene.d.ts +38 -0
  154. package/dist/tools/view-scene.d.ts.map +1 -0
  155. package/dist/tools/view-scene.js +63 -0
  156. package/dist/version.d.ts +5 -0
  157. package/dist/version.d.ts.map +1 -1
  158. package/dist/version.js +17 -3
  159. package/examples/embed-in-agent.ts +1 -1
  160. package/examples/generate-apartment.md +9 -11
  161. package/examples/photo-to-scene.md +1 -1
  162. package/examples/renovate-from-photos.md +3 -4
  163. package/package.json +12 -6
  164. package/dist/tools/create-level.d.ts +0 -21
  165. package/dist/tools/create-level.d.ts.map +0 -1
  166. package/dist/tools/create-level.js +0 -63
  167. package/dist/tools/create-wall.d.ts +0 -22
  168. package/dist/tools/create-wall.d.ts.map +0 -1
  169. package/dist/tools/create-wall.js +0 -57
  170. package/dist/tools/cut-opening.d.ts +0 -25
  171. package/dist/tools/cut-opening.d.ts.map +0 -1
  172. package/dist/tools/cut-opening.js +0 -61
  173. package/dist/tools/delete-node.d.ts +0 -19
  174. package/dist/tools/delete-node.d.ts.map +0 -1
  175. package/dist/tools/delete-node.js +0 -40
  176. package/dist/tools/door-clearance.d.ts +0 -135
  177. package/dist/tools/door-clearance.d.ts.map +0 -1
  178. package/dist/tools/door-clearance.js +0 -334
  179. package/dist/tools/duplicate-level.d.ts +0 -19
  180. package/dist/tools/duplicate-level.d.ts.map +0 -1
  181. package/dist/tools/duplicate-level.js +0 -60
  182. package/dist/tools/geometry.d.ts +0 -24
  183. package/dist/tools/geometry.d.ts.map +0 -1
  184. package/dist/tools/geometry.js +0 -94
  185. package/dist/tools/get-node.d.ts +0 -11
  186. package/dist/tools/get-node.d.ts.map +0 -1
  187. package/dist/tools/get-node.js +0 -29
  188. package/dist/tools/layout-clearance.d.ts +0 -105
  189. package/dist/tools/layout-clearance.d.ts.map +0 -1
  190. package/dist/tools/layout-clearance.js +0 -190
  191. package/dist/tools/place-item.d.ts +0 -22
  192. package/dist/tools/place-item.d.ts.map +0 -1
  193. package/dist/tools/place-item.js +0 -89
  194. package/dist/tools/scene-query.d.ts +0 -62
  195. package/dist/tools/scene-query.d.ts.map +0 -1
  196. package/dist/tools/scene-query.js +0 -670
@@ -0,0 +1,253 @@
1
+ import { nodeRegistry, planNodeDeletion, previewDefaultGutterRefresh, validateNodeRelations, } from '@pascal-app/core';
2
+ import { scriptedFieldRefusal, unknownMaterialPresetRefusal, } from '@pascal-app/core/agent-operations';
3
+ import { AnyNode, nodeKindOf, parseNode } from '@pascal-app/core/schema';
4
+ const guards = [];
5
+ /** Runs a guard on every apply_patch from now on; registering a guard again replaces it. */
6
+ export function registerPatchGuard(guard) {
7
+ const at = guards.findIndex((known) => known.name === guard.name);
8
+ if (at >= 0)
9
+ guards[at] = guard;
10
+ else
11
+ guards.push(guard);
12
+ guards.sort((a, b) => a.order - b.order);
13
+ }
14
+ export function runPatchGuards(patches, nodes) {
15
+ for (const guard of guards)
16
+ guard.run(patches, nodes);
17
+ }
18
+ /**
19
+ * A patch op refused because it would break node identity, the hierarchy or
20
+ * the node's schema. apply_patch returns it as a tool error whose text is
21
+ * JSON `{ code, patchIndex, id, message }`.
22
+ */
23
+ export class PatchRefusedError extends Error {
24
+ code;
25
+ patchIndex;
26
+ nodeId;
27
+ constructor(code, patchIndex, nodeId, detail) {
28
+ super(`${code}: patches[${patchIndex}] ${detail}`);
29
+ this.code = code;
30
+ this.patchIndex = patchIndex;
31
+ this.nodeId = nodeId;
32
+ this.name = 'PatchRefusedError';
33
+ }
34
+ }
35
+ /**
36
+ * Fields an update may restate but not change: `id` and `type` are the node's
37
+ * identity, `object` and `children` its place in the graph. `parentId` stays
38
+ * writable, checked below: the store reconciles both parents' `children`.
39
+ */
40
+ const IMMUTABLE_FIELDS = [
41
+ ['id', 'identity_change'],
42
+ ['type', 'identity_change'],
43
+ ['object', 'immutable_field'],
44
+ ['children', 'immutable_field'],
45
+ ];
46
+ const CORE_KINDS = new Set(AnyNode.options.map(nodeKindOf));
47
+ const sameValue = (a, b) => JSON.stringify(a) === JSON.stringify(b);
48
+ /**
49
+ * Schema issues of a node, keyed `path: message`, from its kind's schema: the
50
+ * registered definition's, or the core per-kind schema. `null` only for a kind
51
+ * with neither (a plugin kind this runtime has not registered), which is then
52
+ * not validated.
53
+ */
54
+ function schemaIssues(node) {
55
+ const type = node.type;
56
+ if (typeof type !== 'string')
57
+ return null;
58
+ const schema = nodeRegistry.get(type)?.schema;
59
+ if (!(schema || CORE_KINDS.has(type)))
60
+ return null;
61
+ const result = schema ? schema.safeParse(node) : parseNode(node);
62
+ const issues = result.success ? [] : (result.error?.issues ?? []);
63
+ return new Set(issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`));
64
+ }
65
+ function withChild(parent, childId) {
66
+ const children = parent.children;
67
+ if (!Array.isArray(children) || children.includes(childId))
68
+ return parent;
69
+ return { ...parent, children: [...children, childId] };
70
+ }
71
+ function withoutChild(parent, childId) {
72
+ const children = parent.children;
73
+ if (!Array.isArray(children))
74
+ return parent;
75
+ return { ...parent, children: children.filter((id) => id !== childId) };
76
+ }
77
+ /**
78
+ * Dry-runs a patch against the scene as each op leaves it and refuses:
79
+ * - a create whose id is already present (`node_exists`): a silent replace
80
+ * orphans the old node's children;
81
+ * - an update that changes `id`, `type`, `object` or `children`
82
+ * (`immutable_field`); restating the current value passes;
83
+ * - an update whose merged node has schema issues the node did not have
84
+ * before (`invalid_update`); kinds without a schema in this runtime pass;
85
+ * - an update writing a material preset the catalog does not know
86
+ * (`invalid_update`; a create is rejected like other invalid creates): it
87
+ * would render as the default finish;
88
+ * - an update of what a node's script owns, its `source` or the size it
89
+ * built (`scripted_field`): only a rebuild keeps them and the geometry in step;
90
+ * - any op on a node an earlier delete in the patch removed, or on a default
91
+ * gutter or downspout that delete regenerates, and any update of the roof
92
+ * segment holding them (`regenerated_default`).
93
+ *
94
+ * Deletes run through the bridge's own deletion preview (`planDeletion`; the
95
+ * local bridge uses core's store planner), one call per run of consecutive
96
+ * deletes as the bridge batches them, so cascades and wall merges are seen as
97
+ * that bridge applies them. A bridge without a preview gets a stricter rule:
98
+ * a create may not reuse any id present at the start of the patch.
99
+ * An update of a roof segment unsettles the default gutters its refresh may
100
+ * regenerate, as a delete does.
101
+ * Lives in the tool layer so every bridge behind `apply_patch` inherits it.
102
+ */
103
+ export function assertPatchKeepsIdentity(patches, nodes, rootNodeIds, planDeletion) {
104
+ const initialIds = new Set(Object.keys(nodes));
105
+ let scene = {
106
+ nodes: { ...nodes },
107
+ rootNodeIds: [...rootNodeIds],
108
+ collections: {},
109
+ };
110
+ const at = (id) => scene.nodes[id];
111
+ const put = (node) => {
112
+ scene.nodes[node.id] = node;
113
+ };
114
+ // Default gutters and downspouts a delete run refreshes: the store may keep,
115
+ // move or replace them with freshly minted ids, so later ops in the same
116
+ // patch cannot address them reliably.
117
+ const regenerated = new Map();
118
+ // Roof segments whose `children` that refresh rewrites: an update restating
119
+ // their pre-delete children would bring back obsolete ids.
120
+ const regeneratedHosts = new Map();
121
+ const refuseRegenerated = (index, id) => {
122
+ const deleteIndex = regenerated.get(id);
123
+ if (deleteIndex === undefined)
124
+ return;
125
+ throw new PatchRefusedError('regenerated_default', index, id, `"${id}" is a default gutter or downspout that the edit at patches[${deleteIndex}] regenerates. Address it in a separate apply_patch call.`);
126
+ };
127
+ // Updating a roof or roof segment makes the store refresh that roof's
128
+ // default gutters, with the same effect on ids as a delete's refresh.
129
+ const unsettleRoofRefresh = (node, index) => {
130
+ const roofId = node.type === 'roof' ? node.id : node.type === 'roof-segment' ? node.parentId : null;
131
+ if (!roofId)
132
+ return;
133
+ const preview = previewDefaultGutterRefresh(scene.nodes, [roofId]);
134
+ for (const id of preview.unsettledIds)
135
+ regenerated.set(id, index);
136
+ for (const id of preview.regeneratedHostIds)
137
+ regeneratedHosts.set(id, index);
138
+ };
139
+ let pendingDeletes = [];
140
+ const flushDeletes = (index) => {
141
+ const plan = planDeletion
142
+ ? planDeletion(scene, pendingDeletes)
143
+ : planNodeDeletion(scene, pendingDeletes, { mintDefaults: false });
144
+ for (const id of plan.unsettledIds)
145
+ regenerated.set(id, index);
146
+ for (const id of plan.regeneratedHostIds)
147
+ regeneratedHosts.set(id, index);
148
+ scene = { nodes: plan.nodes, rootNodeIds: plan.rootNodeIds, collections: plan.collections };
149
+ pendingDeletes = [];
150
+ };
151
+ patches.forEach((patch, index) => {
152
+ if (patch.op === 'create') {
153
+ // Parse like the store does, so defaults such as an empty `children`
154
+ // list exist for later ops in the patch; the bridge reports schema errors.
155
+ const parsed = parseNode(patch.node);
156
+ const node = (parsed.success ? parsed.data : patch.node);
157
+ if (typeof node?.id !== 'string')
158
+ return;
159
+ const preset = unknownMaterialPresetRefusal(node);
160
+ if (preset)
161
+ throw new Error(`invalid patch: patches[${index}] create "${node.id}": ${preset}`);
162
+ refuseRegenerated(index, node.id);
163
+ const effectiveParentId = patch.parentId ?? node.parentId;
164
+ if (effectiveParentId)
165
+ refuseRegenerated(index, effectiveParentId);
166
+ if (at(node.id) || (!planDeletion && initialIds.has(node.id))) {
167
+ throw new PatchRefusedError('node_exists', index, node.id, planDeletion || at(node.id)
168
+ ? `create id "${node.id}" already exists. Use op "update" to change it, or delete it earlier in the same patch to replace it.`
169
+ : `create id "${node.id}" existed when the patch started, and this bridge cannot preview its deletes. Delete it in one apply_patch call and create it in the next.`);
170
+ }
171
+ const parentId = patch.parentId ?? node.parentId ?? null;
172
+ if (patch.parentId !== undefined && !at(patch.parentId)) {
173
+ throw new Error(`invalid patch: patches[${index}] create parentId "${patch.parentId}" not found`);
174
+ }
175
+ put({ ...node, parentId });
176
+ const parent = parentId ? at(parentId) : undefined;
177
+ if (parent)
178
+ put(withChild(parent, node.id));
179
+ return;
180
+ }
181
+ if (patch.op === 'update') {
182
+ refuseRegenerated(index, patch.id);
183
+ const hostDeleteIndex = regeneratedHosts.get(patch.id);
184
+ if (hostDeleteIndex !== undefined) {
185
+ throw new PatchRefusedError('regenerated_default', index, patch.id, `the edit at patches[${hostDeleteIndex}] regenerates the default gutters and downspouts under "${patch.id}", so its children are not known yet. Update it in a separate apply_patch call.`);
186
+ }
187
+ if (typeof patch.data?.parentId === 'string')
188
+ refuseRegenerated(index, patch.data.parentId);
189
+ const current = at(patch.id);
190
+ if (!current)
191
+ throw new Error(`invalid patch: patches[${index}] update id "${patch.id}" not found`);
192
+ if (!patch.data || typeof patch.data !== 'object')
193
+ return;
194
+ const data = patch.data;
195
+ for (const [field, code] of IMMUTABLE_FIELDS) {
196
+ const before = current[field];
197
+ if (field in data && !sameValue(data[field], before)) {
198
+ throw new PatchRefusedError(code, index, patch.id, `update cannot change "${field}" of "${patch.id}" (${JSON.stringify(before)} → ${JSON.stringify(data[field])}). Create a new node, delete the old one, or reparent children through their own parentId.`);
199
+ }
200
+ }
201
+ const scripted = scriptedFieldRefusal(current, data);
202
+ if (scripted)
203
+ throw new PatchRefusedError('scripted_field', index, patch.id, scripted);
204
+ const preset = unknownMaterialPresetRefusal(data, current);
205
+ if (preset)
206
+ throw new PatchRefusedError('invalid_update', index, patch.id, preset);
207
+ const merged = { ...current, ...data };
208
+ const issuesAfter = schemaIssues(merged);
209
+ if (issuesAfter && issuesAfter.size > 0) {
210
+ const issuesBefore = schemaIssues(current) ?? new Set();
211
+ const added = [...issuesAfter].filter((issue) => !issuesBefore.has(issue));
212
+ if (added.length > 0) {
213
+ throw new PatchRefusedError('invalid_update', index, patch.id, `update of ${current.type} "${patch.id}" fails its schema: ${added.slice(0, 5).join('; ')}`);
214
+ }
215
+ }
216
+ if ('parentId' in data && data.parentId !== current.parentId) {
217
+ const newParent = typeof data.parentId === 'string' ? at(data.parentId) : undefined;
218
+ if (!(newParent && Array.isArray(newParent.children))) {
219
+ throw new PatchRefusedError('invalid_parent', index, patch.id, `update cannot move "${patch.id}" under ${JSON.stringify(data.parentId)}: ${newParent ? `a ${newParent.type} holds no children` : 'no such node'}.`);
220
+ }
221
+ const before = { ...scene.nodes };
222
+ const oldParent = current.parentId ? at(current.parentId) : undefined;
223
+ if (oldParent)
224
+ put(withoutChild(oldParent, patch.id));
225
+ put(withChild(newParent, patch.id));
226
+ put(merged);
227
+ unsettleRoofRefresh(merged, index);
228
+ try {
229
+ validateNodeRelations(before, scene.nodes, [patch.id]);
230
+ }
231
+ catch (err) {
232
+ throw new PatchRefusedError('invalid_parent', index, patch.id, `${newParent.type} "${newParent.id}" does not accept "${patch.id}": ${err instanceof Error ? err.message : String(err)}`);
233
+ }
234
+ return;
235
+ }
236
+ put(merged);
237
+ unsettleRoofRefresh(merged, index);
238
+ return;
239
+ }
240
+ if (patch.op === 'delete') {
241
+ refuseRegenerated(index, patch.id);
242
+ if (!at(patch.id) || pendingDeletes.includes(patch.id)) {
243
+ throw new Error(`invalid patch: patches[${index}] delete id "${patch.id}" not found`);
244
+ }
245
+ pendingDeletes.push(patch.id);
246
+ // The bridge applies a run of consecutive deletes as one deleteNodes
247
+ // call, and wall merges and kind cascades depend on the whole id list,
248
+ // so plan the run together once it ends.
249
+ if (patches[index + 1]?.op !== 'delete')
250
+ flushDeletes(index);
251
+ }
252
+ });
253
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"photo-to-scene.d.ts","sourceRoot":"","sources":["../../../src/tools/photo-to-scene/photo-to-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAYxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;CAa7B,CAAA;AAED,eAAO,MAAM,kBAAkB;;;;;;;;CAQ9B,CAAA;AAmTD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA8ErF"}
1
+ {"version":3,"file":"photo-to-scene.d.ts","sourceRoot":"","sources":["../../../src/tools/photo-to-scene/photo-to-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAMxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;CAa7B,CAAA;AAED,eAAO,MAAM,kBAAkB;;;;;;;;CAQ9B,CAAA;AAmTD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA8ErF"}
@@ -1,5 +1,6 @@
1
1
  import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
2
- import { AnyNode, BuildingNode, LevelNode, SiteNode, WallNode, ZoneNode, } from '@pascal-app/core/schema';
2
+ import { newZone } from '@pascal-app/core';
3
+ import { AnyNode, BuildingNode, LevelNode, SiteNode, WallNode } from '@pascal-app/core/schema';
3
4
  import { z } from 'zod';
4
5
  import { DESTRUCTIVE_OPEN_WORLD_TOOL_ANNOTATIONS } from '../annotations.js';
5
6
  import { appendLiveSceneEvent } from '../live-sync.js';
@@ -236,7 +237,7 @@ function buildSceneGraphFromVision(vision, defaultWallThickness, defaultWallHeig
236
237
  for (let i = 0; i < vision.rooms.length; i++) {
237
238
  const r = vision.rooms[i];
238
239
  try {
239
- const zone = ZoneNode.parse({
240
+ const zone = newZone({
240
241
  name: r.name,
241
242
  polygon: r.polygon,
242
243
  });
@@ -0,0 +1,34 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+ import type { SceneOperations } from '../operations/index.js';
4
+ export declare const placeDesignInput: {
5
+ design: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>;
6
+ hostId: z.ZodString;
7
+ position: z.ZodArray<z.ZodNumber>;
8
+ rotation: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
9
+ side: z.ZodOptional<z.ZodEnum<{
10
+ front: "front";
11
+ back: "back";
12
+ }>>;
13
+ surfaceId: z.ZodOptional<z.ZodString>;
14
+ parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
15
+ slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
16
+ name: z.ZodOptional<z.ZodString>;
17
+ id: z.ZodOptional<z.ZodString>;
18
+ };
19
+ export declare const placeDesignOutput: {
20
+ project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
21
+ unsaved: z.ZodOptional<z.ZodString>;
22
+ persistence: z.ZodOptional<z.ZodObject<{
23
+ status: z.ZodEnum<{
24
+ unbound: "unbound";
25
+ events_unsupported: "events_unsupported";
26
+ }>;
27
+ warning: z.ZodString;
28
+ }, z.core.$strip>>;
29
+ designId: z.ZodString;
30
+ parentId: z.ZodString;
31
+ surfaceId: z.ZodNullable<z.ZodString>;
32
+ };
33
+ export declare function registerPlaceDesign(server: McpServer, bridge: SceneOperations): void;
34
+ //# sourceMappingURL=place-design.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"place-design.d.ts","sourceRoot":"","sources":["../../src/tools/place-design.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAOpD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;CA8B5B,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;CAK7B,CAAA;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAyDpF"}
@@ -0,0 +1,91 @@
1
+ import { DesignPlacementError, planDesignPlacement } from '@pascal-app/core/procedural-items';
2
+ import { z } from 'zod';
3
+ import { ADDITIVE_TOOL_ANNOTATIONS } from './annotations.js';
4
+ import { liveSyncOutput, persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
5
+ import { measurement } from './measurement.js';
6
+ import { NodeIdSchema, Vec3Schema } from './schemas.js';
7
+ import { validateDesignInput } from './validate-design.js';
8
+ export const placeDesignInput = {
9
+ design: validateDesignInput.design,
10
+ hostId: NodeIdSchema.describe('Floor designs: a level, or a slab or zone on it, or a placed design with surfaceId. Wall-side designs: a straight wall. Ceiling designs: a ceiling.'),
11
+ position: Vec3Schema.describe('Metres. Floor: level-local [x, y, z], y above the floor. Wall-side: [along, height, offset] of the mounting reference from the wall start. Ceiling: plan [x, 0, z] of the reference. Surface: [x, 0, z] in the surface frame.'),
12
+ rotation: measurement('angle', 'rad', {
13
+ description: 'Yaw. Not for wall-side designs; use side to face the other way.',
14
+ }).optional(),
15
+ side: z.enum(['front', 'back']).optional().describe('Wall face for wall-side designs.'),
16
+ surfaceId: z
17
+ .string()
18
+ .optional()
19
+ .describe('Named surface of the host design to rest on (see validate_design measurements.surfaces).'),
20
+ parameters: validateDesignInput.parameters,
21
+ slots: z
22
+ .record(z.string(), z.string())
23
+ .optional()
24
+ .describe('Slot id to "#rrggbb" or a scene:/library: material reference.'),
25
+ name: z.string().optional(),
26
+ id: z
27
+ .string()
28
+ .optional()
29
+ .describe('Optional new id ("procedural-item_…"). Refused if it exists: this tool only creates.'),
30
+ };
31
+ export const placeDesignOutput = {
32
+ designId: z.string(),
33
+ parentId: z.string(),
34
+ surfaceId: z.string().nullable(),
35
+ ...liveSyncOutput,
36
+ };
37
+ export function registerPlaceDesign(server, bridge) {
38
+ server.registerTool('place_design', {
39
+ title: 'Place design',
40
+ description: 'Create one instance of a design (procedural item recipe, object or JSON string) in the scene. The design must pass validate_design. Its mounting picks the host: floor designs go on a level (or a slab or zone of it) or on a named surface of a placed design; wall-side designs on a straight wall face; ceiling designs under a ceiling. Only creates: refusals are tool errors whose JSON carries a code (invalid_design with diagnostics, design_version_not_enabled for version 2 designs until the next release, design_too_large above 24 KiB, invalid_placement, node_exists, host_not_found, wrong_host, unknown_surface, does_not_fit) and change nothing.',
41
+ inputSchema: placeDesignInput,
42
+ outputSchema: placeDesignOutput,
43
+ annotations: ADDITIVE_TOOL_ANNOTATIONS,
44
+ }, async (args) => {
45
+ const refuse = (refusal) => ({
46
+ content: [{ type: 'text', text: JSON.stringify(refusal) }],
47
+ isError: true,
48
+ });
49
+ let placement;
50
+ try {
51
+ placement = planDesignPlacement(bridge.getNodes(), {
52
+ ...args,
53
+ position: args.position,
54
+ });
55
+ }
56
+ catch (error) {
57
+ if (!(error instanceof DesignPlacementError))
58
+ throw error;
59
+ return refuse({
60
+ code: error.code,
61
+ message: error.message,
62
+ ...(error.diagnostics.length > 0 && { diagnostics: error.diagnostics.slice(0, 8) }),
63
+ });
64
+ }
65
+ const { node, parentId, hostUpdate } = placement;
66
+ const patches = [
67
+ { op: 'create', node: node, parentId: parentId },
68
+ ...(hostUpdate
69
+ ? [
70
+ {
71
+ op: 'update',
72
+ id: hostUpdate.id,
73
+ data: { attachments: hostUpdate.attachments },
74
+ },
75
+ ]
76
+ : []),
77
+ ];
78
+ bridge.applyPatch(patches);
79
+ const persistence = await publishLiveSceneSnapshot(bridge, 'place_design');
80
+ const payload = {
81
+ designId: node.id,
82
+ parentId,
83
+ surfaceId: args.surfaceId ?? null,
84
+ ...persistencePayload(persistence),
85
+ };
86
+ return {
87
+ content: [{ type: 'text', text: JSON.stringify(payload) }],
88
+ structuredContent: payload,
89
+ };
90
+ });
91
+ }
@@ -5,6 +5,8 @@ export declare const redoInput: {
5
5
  steps: z.ZodOptional<z.ZodNumber>;
6
6
  };
7
7
  export declare const redoOutput: {
8
+ project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
9
+ unsaved: z.ZodOptional<z.ZodString>;
8
10
  persistence: z.ZodOptional<z.ZodObject<{
9
11
  status: z.ZodEnum<{
10
12
  unbound: "unbound";
@@ -1 +1 @@
1
- {"version":3,"file":"redo.d.ts","sourceRoot":"","sources":["../../src/tools/redo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAIpD,eAAO,MAAM,SAAS;;CAErB,CAAA;AAED,eAAO,MAAM,UAAU;;;;;;;;;CAGtB,CAAA;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAsB7E"}
1
+ {"version":3,"file":"redo.d.ts","sourceRoot":"","sources":["../../src/tools/redo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AASpD,eAAO,MAAM,SAAS;;CAErB,CAAA;AAED,eAAO,MAAM,UAAU;;;;;;;;;;;CAGtB,CAAA;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAsB7E"}
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { DESTRUCTIVE_TOOL_ANNOTATIONS } from './annotations.js';
3
- import { liveSyncOutput, persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
3
+ import { currentLiveSync, liveSyncOutput, persistencePayload, publishLiveSceneSnapshot, } from './live-sync.js';
4
4
  export const redoInput = {
5
5
  steps: z.number().int().positive().optional(),
6
6
  };
@@ -17,7 +17,7 @@ export function registerRedo(server, bridge) {
17
17
  annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
18
18
  }, async ({ steps }) => {
19
19
  const redone = bridge.redo(steps ?? 1);
20
- const persistence = redone > 0 ? await publishLiveSceneSnapshot(bridge, 'redo') : 'published';
20
+ const persistence = redone > 0 ? await publishLiveSceneSnapshot(bridge, 'redo') : currentLiveSync(bridge);
21
21
  const payload = { redone, ...persistencePayload(persistence) };
22
22
  return {
23
23
  content: [{ type: 'text', text: JSON.stringify(payload) }],
@@ -1,125 +1,62 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { z } from 'zod';
3
2
  import type { SceneOperations } from '../operations/index.js';
4
- export declare const searchAssetsInput: {
5
- query: z.ZodString;
6
- category: z.ZodOptional<z.ZodString>;
7
- };
8
- export declare const searchAssetsOutput: {
9
- results: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
10
- total: z.ZodNumber;
11
- };
12
- export declare const createRoomInput: {
13
- levelId: z.ZodString;
14
- name: z.ZodString;
15
- polygon: z.ZodArray<z.ZodArray<z.ZodNumber>>;
16
- color: z.ZodOptional<z.ZodString>;
17
- wallHeight: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
18
- wallThickness: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
19
- };
20
- export declare const createRoomOutput: {
21
- persistence: z.ZodOptional<z.ZodObject<{
22
- status: z.ZodEnum<{
23
- unbound: "unbound";
24
- events_unsupported: "events_unsupported";
25
- }>;
26
- warning: z.ZodString;
27
- }, z.core.$strip>>;
28
- zoneId: z.ZodString;
29
- slabId: z.ZodString;
30
- ceilingId: z.ZodString;
31
- wallIds: z.ZodArray<z.ZodString>;
32
- areaSqMeters: z.ZodNumber;
33
- };
34
- export declare const addDoorInput: {
35
- wallId: z.ZodString;
36
- t: z.ZodOptional<z.ZodNumber>;
37
- position: z.ZodOptional<z.ZodNumber>;
38
- width: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
39
- height: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
40
- hingesSide: z.ZodOptional<z.ZodEnum<{
41
- right: "right";
42
- left: "left";
43
- }>>;
44
- swingDirection: z.ZodOptional<z.ZodEnum<{
45
- inward: "inward";
46
- outward: "outward";
47
- }>>;
48
- };
3
+ import { type GeometryScriptHost } from './add-object.js';
4
+ /** The contract's one result (core `addWallOpening`), and the live sync's note. */
49
5
  export declare const addDoorOutput: {
50
- persistence: z.ZodOptional<z.ZodObject<{
51
- status: z.ZodEnum<{
6
+ project: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
7
+ unsaved: import("zod").ZodOptional<import("zod").ZodString>;
8
+ persistence: import("zod").ZodOptional<import("zod").ZodObject<{
9
+ status: import("zod").ZodEnum<{
52
10
  unbound: "unbound";
53
11
  events_unsupported: "events_unsupported";
54
12
  }>;
55
- warning: z.ZodString;
56
- }, z.core.$strip>>;
57
- doorId: z.ZodString;
58
- localX: z.ZodNumber;
59
- t: z.ZodNumber;
60
- position: z.ZodNumber;
61
- wallLength: z.ZodNumber;
62
- clamped: z.ZodBoolean;
63
- coordinateSystem: z.ZodLiteral<"wall-local-meters">;
64
- };
65
- export declare const addWindowInput: {
66
- wallId: z.ZodString;
67
- t: z.ZodOptional<z.ZodNumber>;
68
- position: z.ZodOptional<z.ZodNumber>;
69
- width: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
70
- height: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
71
- sillHeight: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
13
+ warning: import("zod").ZodString;
14
+ }, import("zod/v4/core").$strip>>;
15
+ ok: import("zod").ZodLiteral<true>;
16
+ wallId: import("zod").ZodString;
17
+ localX: import("zod").ZodNumber;
18
+ t: import("zod").ZodNumber;
19
+ wallLength: import("zod").ZodNumber;
20
+ clamped: import("zod").ZodBoolean;
21
+ coordinateSystem: import("zod").ZodLiteral<"wall-local-meters">;
22
+ message: import("zod").ZodString;
23
+ achieved: import("zod").ZodObject<{
24
+ created: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
25
+ updated: import("zod").ZodNumber;
26
+ deleted: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
27
+ unchanged: import("zod").ZodOptional<import("zod").ZodLiteral<true>>;
28
+ }, import("zod/v4/core").$strip>;
29
+ doorId: import("zod").ZodString;
72
30
  };
73
31
  export declare const addWindowOutput: {
74
- persistence: z.ZodOptional<z.ZodObject<{
75
- status: z.ZodEnum<{
32
+ project: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
33
+ unsaved: import("zod").ZodOptional<import("zod").ZodString>;
34
+ persistence: import("zod").ZodOptional<import("zod").ZodObject<{
35
+ status: import("zod").ZodEnum<{
76
36
  unbound: "unbound";
77
37
  events_unsupported: "events_unsupported";
78
38
  }>;
79
- warning: z.ZodString;
80
- }, z.core.$strip>>;
81
- windowId: z.ZodString;
82
- localX: z.ZodNumber;
83
- t: z.ZodNumber;
84
- position: z.ZodNumber;
85
- wallLength: z.ZodNumber;
86
- clamped: z.ZodBoolean;
87
- coordinateSystem: z.ZodLiteral<"wall-local-meters">;
88
- sillHeight: z.ZodNumber;
89
- };
90
- export declare const furnishRoomInput: {
91
- levelId: z.ZodOptional<z.ZodString>;
92
- zoneId: z.ZodOptional<z.ZodString>;
93
- roomType: z.ZodEnum<{
94
- bedroom: "bedroom";
95
- storage: "storage";
96
- living: "living";
97
- dining: "dining";
98
- kitchen: "kitchen";
99
- bathroom: "bathroom";
100
- laundry: "laundry";
101
- entry: "entry";
102
- hallway: "hallway";
103
- }>;
104
- polygon: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodNumber>>>;
105
- doorWallIndex: z.ZodOptional<z.ZodNumber>;
106
- };
107
- export declare const furnishRoomOutput: {
108
- persistence: z.ZodOptional<z.ZodObject<{
109
- status: z.ZodEnum<{
110
- unbound: "unbound";
111
- events_unsupported: "events_unsupported";
112
- }>;
113
- warning: z.ZodString;
114
- }, z.core.$strip>>;
115
- placed: z.ZodNumber;
116
- itemIds: z.ZodArray<z.ZodString>;
117
- skipped: z.ZodArray<z.ZodString>;
118
- };
119
- export declare function registerSearchAssets(server: McpServer): void;
120
- export declare function registerCreateRoom(server: McpServer, bridge: SceneOperations): void;
121
- export declare function registerAddDoor(server: McpServer, bridge: SceneOperations): void;
122
- export declare function registerAddWindow(server: McpServer, bridge: SceneOperations): void;
123
- export declare function registerFurnishRoom(server: McpServer, bridge: SceneOperations): void;
124
- export declare function registerRoomTools(server: McpServer, bridge: SceneOperations): void;
39
+ warning: import("zod").ZodString;
40
+ }, import("zod/v4/core").$strip>>;
41
+ sillHeight: import("zod").ZodOptional<import("zod").ZodNumber>;
42
+ ok: import("zod").ZodLiteral<true>;
43
+ wallId: import("zod").ZodString;
44
+ localX: import("zod").ZodNumber;
45
+ t: import("zod").ZodNumber;
46
+ wallLength: import("zod").ZodNumber;
47
+ clamped: import("zod").ZodBoolean;
48
+ coordinateSystem: import("zod").ZodLiteral<"wall-local-meters">;
49
+ message: import("zod").ZodString;
50
+ achieved: import("zod").ZodObject<{
51
+ created: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
52
+ updated: import("zod").ZodNumber;
53
+ deleted: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
54
+ unchanged: import("zod").ZodOptional<import("zod").ZodLiteral<true>>;
55
+ }, import("zod/v4/core").$strip>;
56
+ windowId: import("zod").ZodString;
57
+ };
58
+ export declare function registerAddDoor(server: McpServer, bridge: SceneOperations, geometryScripts?: GeometryScriptHost): void;
59
+ export declare function registerAddWindow(server: McpServer, bridge: SceneOperations, geometryScripts?: GeometryScriptHost): void;
60
+ /** add_door and add_window; create_room and furnish_room are shared tools (shared-tools.ts). */
61
+ export declare function registerRoomTools(server: McpServer, bridge: SceneOperations, geometryScripts?: GeometryScriptHost): void;
125
62
  //# sourceMappingURL=room-tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"room-tools.d.ts","sourceRoot":"","sources":["../../src/tools/room-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAWxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAkCpD,eAAO,MAAM,iBAAiB;;;CAG7B,CAAA;AAED,eAAO,MAAM,kBAAkB;;;CAG9B,CAAA;AAED,eAAO,MAAM,eAAe;;;;;;;CAa3B,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;CAO5B,CAAA;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;;CAQxB,CAAA;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;CASzB,CAAA;AAED,eAAO,MAAM,cAAc;;;;;;;CAU1B,CAAA;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;CAU3B,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;CAM5B,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;CAK7B,CAAA;AA4QD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuB5D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAuDnF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA6ChF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA4ClF;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA0HpF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAMlF"}
1
+ {"version":3,"file":"room-tools.d.ts","sourceRoot":"","sources":["../../src/tools/room-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAyBxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAmB,KAAK,kBAAkB,EAAc,MAAM,cAAc,CAAA;AAMnF,mFAAmF;AACnF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;CAA0C,CAAA;AACpE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;CAA4C,CAAA;AAoHxE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,eAAe,CAAC,EAAE,kBAAkB,GACnC,IAAI,CA8BN;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,eAAe,CAAC,EAAE,kBAAkB,GACnC,IAAI,CA8BN;AAED,gGAAgG;AAChG,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,eAAe,CAAC,EAAE,kBAAkB,GACnC,IAAI,CAGN"}