@pascal-app/mcp 1.0.3 → 1.0.5
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/CHANGELOG.md +76 -0
- package/README.md +181 -56
- package/dist/bin/pascal-mcp.js +9 -3
- package/dist/bridge/agent-session.d.ts +18 -0
- package/dist/bridge/agent-session.d.ts.map +1 -0
- package/dist/bridge/agent-session.js +15 -0
- package/dist/bridge/index.d.ts +1 -1
- package/dist/bridge/index.d.ts.map +1 -1
- package/dist/bridge/scene-bridge.d.ts +42 -6
- package/dist/bridge/scene-bridge.d.ts.map +1 -1
- package/dist/bridge/scene-bridge.js +232 -45
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/safe-fetch.d.ts +22 -4
- package/dist/lib/safe-fetch.d.ts.map +1 -1
- package/dist/lib/safe-fetch.js +233 -134
- package/dist/operations/scene-operations.d.ts +41 -3
- package/dist/operations/scene-operations.d.ts.map +1 -1
- package/dist/operations/scene-operations.js +42 -1
- package/dist/prompts/from-brief.d.ts +1 -1
- package/dist/prompts/from-brief.d.ts.map +1 -1
- package/dist/prompts/from-brief.js +3 -3
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/iterate-on-feedback.d.ts +1 -1
- package/dist/prompts/iterate-on-feedback.d.ts.map +1 -1
- package/dist/prompts/iterate-on-feedback.js +3 -3
- package/dist/prompts/renovation-from-photos.d.ts +1 -1
- package/dist/prompts/renovation-from-photos.d.ts.map +1 -1
- package/dist/prompts/renovation-from-photos.js +2 -2
- package/dist/prompts/scene-guidance.d.ts.map +1 -1
- package/dist/prompts/scene-guidance.js +13 -6
- package/dist/resources/agent-guide.d.ts +1 -1
- package/dist/resources/agent-guide.d.ts.map +1 -1
- package/dist/resources/agent-guide.js +62 -33
- package/dist/resources/catalog-items.d.ts +5 -6
- package/dist/resources/catalog-items.d.ts.map +1 -1
- package/dist/resources/catalog-items.js +7 -9
- package/dist/resources/constraints.d.ts +1 -1
- package/dist/resources/constraints.d.ts.map +1 -1
- package/dist/resources/constraints.js +1 -1
- package/dist/resources/design-schema.d.ts +9 -0
- package/dist/resources/design-schema.d.ts.map +1 -0
- package/dist/resources/design-schema.js +21 -0
- package/dist/resources/index.d.ts +4 -2
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +5 -2
- package/dist/resources/scene-current.d.ts +1 -1
- package/dist/resources/scene-current.d.ts.map +1 -1
- package/dist/resources/scene-summary.d.ts +1 -1
- package/dist/resources/scene-summary.d.ts.map +1 -1
- package/dist/server.d.ts +25 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +71 -25
- package/dist/storage/disk-artifact-store.d.ts +9 -0
- package/dist/storage/disk-artifact-store.d.ts.map +1 -0
- package/dist/storage/disk-artifact-store.js +46 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/sqlite-scene-store.d.ts +3 -3
- package/dist/storage/sqlite-scene-store.d.ts.map +1 -1
- package/dist/storage/sqlite-scene-store.js +4 -3
- package/dist/storage/types.d.ts +36 -7
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/types.js +12 -0
- package/dist/templates/empty-studio.d.ts +3 -3
- package/dist/templates/empty-studio.d.ts.map +1 -1
- package/dist/templates/garden-house.d.ts +3 -3
- package/dist/templates/garden-house.d.ts.map +1 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/two-bedroom.d.ts +3 -3
- package/dist/templates/two-bedroom.d.ts.map +1 -1
- package/dist/tools/add-column.d.ts +5 -0
- package/dist/tools/add-column.d.ts.map +1 -0
- package/dist/tools/add-column.js +59 -0
- package/dist/tools/add-object.d.ts +76 -0
- package/dist/tools/add-object.d.ts.map +1 -0
- package/dist/tools/add-object.js +187 -0
- package/dist/tools/annotations.d.ts.map +1 -1
- package/dist/tools/apply-patch.d.ts +9 -2
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +36 -5
- package/dist/tools/asset-catalog.d.ts +9 -5
- package/dist/tools/asset-catalog.d.ts.map +1 -1
- package/dist/tools/asset-catalog.js +33 -12
- package/dist/tools/author-scene.d.ts +10 -0
- package/dist/tools/author-scene.d.ts.map +1 -0
- package/dist/tools/author-scene.js +140 -0
- package/dist/tools/check-collisions.d.ts +7 -7
- package/dist/tools/check-collisions.d.ts.map +1 -1
- package/dist/tools/check-collisions.js +7 -8
- package/dist/tools/clear-scene.d.ts +9 -0
- package/dist/tools/clear-scene.d.ts.map +1 -0
- package/dist/tools/clear-scene.js +59 -0
- package/dist/tools/collections.d.ts +4 -0
- package/dist/tools/collections.d.ts.map +1 -0
- package/dist/tools/collections.js +53 -0
- package/dist/tools/construction-tools.d.ts +12 -88
- package/dist/tools/construction-tools.d.ts.map +1 -1
- package/dist/tools/construction-tools.js +122 -381
- package/dist/tools/create-unit.d.ts +5 -3
- package/dist/tools/create-unit.d.ts.map +1 -1
- package/dist/tools/create-unit.js +2 -2
- package/dist/tools/errors.d.ts +15 -4
- package/dist/tools/errors.d.ts.map +1 -1
- package/dist/tools/errors.js +14 -4
- package/dist/tools/export-glb.d.ts +1 -1
- package/dist/tools/export-glb.d.ts.map +1 -1
- package/dist/tools/export-glb.js +2 -2
- package/dist/tools/export-json.d.ts +1 -1
- package/dist/tools/export-json.d.ts.map +1 -1
- package/dist/tools/export-json.js +2 -2
- package/dist/tools/geometry-script-worker.d.ts +2 -0
- package/dist/tools/geometry-script-worker.d.ts.map +1 -0
- package/dist/tools/geometry-script-worker.js +21 -0
- package/dist/tools/get-scene.d.ts +2 -1
- package/dist/tools/get-scene.d.ts.map +1 -1
- package/dist/tools/get-scene.js +5 -3
- package/dist/tools/honest-patch-guard.d.ts +2 -0
- package/dist/tools/honest-patch-guard.d.ts.map +1 -0
- package/dist/tools/honest-patch-guard.js +32 -0
- package/dist/tools/hosted-services.d.ts +4 -0
- package/dist/tools/hosted-services.d.ts.map +1 -0
- package/dist/tools/hosted-services.js +40 -0
- package/dist/tools/index.d.ts +12 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +18 -32
- package/dist/tools/level-height-guard.d.ts +2 -0
- package/dist/tools/level-height-guard.d.ts.map +1 -0
- package/dist/tools/level-height-guard.js +11 -0
- package/dist/tools/list-units.d.ts +2 -2
- package/dist/tools/list-units.d.ts.map +1 -1
- package/dist/tools/list-units.js +2 -2
- package/dist/tools/live-sync.d.ts +25 -6
- package/dist/tools/live-sync.d.ts.map +1 -1
- package/dist/tools/live-sync.js +48 -27
- package/dist/tools/local-geometry-scripts.d.ts +8 -0
- package/dist/tools/local-geometry-scripts.d.ts.map +1 -0
- package/dist/tools/local-geometry-scripts.js +67 -0
- package/dist/tools/measure.d.ts +7 -1
- package/dist/tools/measure.d.ts.map +1 -1
- package/dist/tools/measure.js +38 -70
- package/dist/tools/measurement.d.ts +1 -36
- package/dist/tools/measurement.d.ts.map +1 -1
- package/dist/tools/measurement.js +2 -94
- package/dist/tools/node-world-point.d.ts +37 -0
- package/dist/tools/node-world-point.d.ts.map +1 -0
- package/dist/tools/node-world-point.js +457 -0
- package/dist/tools/normalize-schema-dialect.d.ts +1 -1
- package/dist/tools/normalize-schema-dialect.d.ts.map +1 -1
- package/dist/tools/normalize-schema-dialect.js +22 -3
- package/dist/tools/patch-guards.d.ts +60 -0
- package/dist/tools/patch-guards.d.ts.map +1 -0
- package/dist/tools/patch-guards.js +256 -0
- package/dist/tools/photo-to-scene/index.d.ts +1 -1
- package/dist/tools/photo-to-scene/index.d.ts.map +1 -1
- package/dist/tools/photo-to-scene/photo-to-scene.d.ts +3 -3
- package/dist/tools/photo-to-scene/photo-to-scene.d.ts.map +1 -1
- package/dist/tools/photo-to-scene/photo-to-scene.js +10 -9
- package/dist/tools/project-files.d.ts +4 -0
- package/dist/tools/project-files.d.ts.map +1 -0
- package/dist/tools/project-files.js +30 -0
- package/dist/tools/redo.d.ts +4 -2
- package/dist/tools/redo.d.ts.map +1 -1
- package/dist/tools/redo.js +4 -4
- package/dist/tools/retired-tools.d.ts +10 -0
- package/dist/tools/retired-tools.d.ts.map +1 -0
- package/dist/tools/retired-tools.js +22 -0
- package/dist/tools/roof-level-guard.d.ts +2 -0
- package/dist/tools/roof-level-guard.d.ts.map +1 -0
- package/dist/tools/roof-level-guard.js +22 -0
- package/dist/tools/room-tools.d.ts +36 -98
- package/dist/tools/room-tools.d.ts.map +1 -1
- package/dist/tools/room-tools.js +130 -565
- package/dist/tools/scene-lifecycle/create-project.d.ts +1 -1
- package/dist/tools/scene-lifecycle/create-project.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/create-project.js +31 -6
- package/dist/tools/scene-lifecycle/delete-scene.d.ts +3 -1
- package/dist/tools/scene-lifecycle/delete-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/delete-scene.js +10 -9
- package/dist/tools/scene-lifecycle/get-project-status.d.ts +1 -1
- package/dist/tools/scene-lifecycle/get-project-status.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/get-project-status.js +6 -6
- package/dist/tools/scene-lifecycle/index.d.ts +1 -1
- package/dist/tools/scene-lifecycle/index.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/list-scenes.d.ts +1 -1
- package/dist/tools/scene-lifecycle/list-scenes.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/list-scenes.js +4 -4
- package/dist/tools/scene-lifecycle/load-scene.d.ts +2 -2
- package/dist/tools/scene-lifecycle/load-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/load-scene.js +5 -5
- package/dist/tools/scene-lifecycle/metadata.d.ts +1 -1
- package/dist/tools/scene-lifecycle/rename-scene.d.ts +1 -1
- package/dist/tools/scene-lifecycle/rename-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/rename-scene.js +6 -6
- package/dist/tools/scene-lifecycle/save-scene.d.ts +6 -3
- package/dist/tools/scene-lifecycle/save-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/save-scene.js +124 -16
- package/dist/tools/scene-lifecycle/test-utils.d.ts +3 -3
- package/dist/tools/scene-lifecycle/test-utils.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/test-utils.js +2 -1
- package/dist/tools/set-unit-members.d.ts +4 -2
- package/dist/tools/set-unit-members.d.ts.map +1 -1
- package/dist/tools/set-unit-members.js +6 -6
- package/dist/tools/set-zone.d.ts +4 -2
- package/dist/tools/set-zone.d.ts.map +1 -1
- package/dist/tools/set-zone.js +30 -18
- package/dist/tools/shared-tools.d.ts +40 -0
- package/dist/tools/shared-tools.d.ts.map +1 -0
- package/dist/tools/shared-tools.js +574 -0
- package/dist/tools/structure-tools.d.ts +57 -0
- package/dist/tools/structure-tools.d.ts.map +1 -0
- package/dist/tools/structure-tools.js +57 -0
- package/dist/tools/templates/create-from-template.d.ts +2 -2
- package/dist/tools/templates/create-from-template.d.ts.map +1 -1
- package/dist/tools/templates/create-from-template.js +6 -6
- package/dist/tools/templates/create-house-from-brief.d.ts +1 -1
- package/dist/tools/templates/create-house-from-brief.d.ts.map +1 -1
- package/dist/tools/templates/create-house-from-brief.js +6 -6
- package/dist/tools/templates/index.d.ts +1 -1
- package/dist/tools/templates/index.d.ts.map +1 -1
- package/dist/tools/templates/list-templates.d.ts +1 -1
- package/dist/tools/templates/list-templates.d.ts.map +1 -1
- package/dist/tools/templates/list-templates.js +2 -2
- package/dist/tools/undo.d.ts +4 -2
- package/dist/tools/undo.d.ts.map +1 -1
- package/dist/tools/undo.js +4 -4
- package/dist/tools/unit-members.d.ts.map +1 -1
- package/dist/tools/unit-members.js +6 -6
- package/dist/tools/variants/generate-variants.d.ts +6 -6
- package/dist/tools/variants/generate-variants.d.ts.map +1 -1
- package/dist/tools/variants/generate-variants.js +6 -6
- package/dist/tools/variants/index.d.ts +1 -1
- package/dist/tools/variants/index.d.ts.map +1 -1
- package/dist/tools/variants/mutations.js +1 -1
- package/dist/tools/view-scene.d.ts +44 -0
- package/dist/tools/view-scene.d.ts.map +1 -0
- package/dist/tools/view-scene.js +75 -0
- package/dist/tools/vision/analyze-floorplan-image.d.ts +1 -1
- package/dist/tools/vision/analyze-floorplan-image.d.ts.map +1 -1
- package/dist/tools/vision/analyze-floorplan-image.js +7 -7
- package/dist/tools/vision/analyze-room-photo.d.ts +1 -1
- package/dist/tools/vision/analyze-room-photo.d.ts.map +1 -1
- package/dist/tools/vision/analyze-room-photo.js +7 -7
- package/dist/tools/vision/index.d.ts +1 -1
- package/dist/tools/vision/index.d.ts.map +1 -1
- package/dist/transports/http.d.ts +8 -2
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +9 -3
- package/dist/transports/stdio.d.ts +15 -9
- package/dist/transports/stdio.d.ts.map +1 -1
- package/dist/transports/stdio.js +18 -11
- package/dist/version.d.ts +5 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +17 -3
- package/examples/coordinate-conventions-demo.md +12 -13
- package/examples/embed-in-agent.ts +6 -7
- package/examples/generate-apartment.md +13 -15
- package/examples/photo-to-scene.md +3 -4
- package/examples/renovate-from-photos.md +6 -9
- package/package.json +19 -9
- package/dist/tools/create-level.d.ts +0 -21
- package/dist/tools/create-level.d.ts.map +0 -1
- package/dist/tools/create-level.js +0 -63
- package/dist/tools/create-wall.d.ts +0 -22
- package/dist/tools/create-wall.d.ts.map +0 -1
- package/dist/tools/create-wall.js +0 -57
- package/dist/tools/cut-opening.d.ts +0 -25
- package/dist/tools/cut-opening.d.ts.map +0 -1
- package/dist/tools/cut-opening.js +0 -61
- package/dist/tools/delete-node.d.ts +0 -19
- package/dist/tools/delete-node.d.ts.map +0 -1
- package/dist/tools/delete-node.js +0 -40
- package/dist/tools/describe-node.d.ts +0 -17
- package/dist/tools/describe-node.d.ts.map +0 -1
- package/dist/tools/describe-node.js +0 -97
- package/dist/tools/door-clearance.d.ts +0 -135
- package/dist/tools/door-clearance.d.ts.map +0 -1
- package/dist/tools/door-clearance.js +0 -334
- package/dist/tools/duplicate-level.d.ts +0 -19
- package/dist/tools/duplicate-level.d.ts.map +0 -1
- package/dist/tools/duplicate-level.js +0 -60
- package/dist/tools/find-nodes.d.ts +0 -32
- package/dist/tools/find-nodes.d.ts.map +0 -1
- package/dist/tools/find-nodes.js +0 -107
- package/dist/tools/geometry.d.ts +0 -24
- package/dist/tools/geometry.d.ts.map +0 -1
- package/dist/tools/geometry.js +0 -94
- package/dist/tools/get-node.d.ts +0 -11
- package/dist/tools/get-node.d.ts.map +0 -1
- package/dist/tools/get-node.js +0 -29
- package/dist/tools/layout-clearance.d.ts +0 -105
- package/dist/tools/layout-clearance.d.ts.map +0 -1
- package/dist/tools/layout-clearance.js +0 -190
- package/dist/tools/place-item.d.ts +0 -22
- package/dist/tools/place-item.d.ts.map +0 -1
- package/dist/tools/place-item.js +0 -89
- package/dist/tools/scene-query.d.ts +0 -62
- package/dist/tools/scene-query.d.ts.map +0 -1
- package/dist/tools/scene-query.js +0 -670
- package/dist/tools/validate-scene.d.ts +0 -19
- package/dist/tools/validate-scene.d.ts.map +0 -1
- package/dist/tools/validate-scene.js +0 -28
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { isScriptedNode, scriptedObjectMeta } from '@pascal-app/core';
|
|
2
|
+
import { achievedChanges, addObject, authoredObject, editedScriptLanguage, editedScriptParams, furnishingRefusal, readableScript, readSourceResult, requireAddObjectReason, } from '@pascal-app/core/agent-operations';
|
|
3
|
+
import { addObjectTool, CATALOG_SOURCE, getSourceTool, isAgentRefusal, refuse, } from '@pascal-app/core/agent-tools';
|
|
4
|
+
import { GEOMETRY_SCRIPT_MIME_TYPES, GeometryArtifactMetadata, GeometryReuseFields, generateId, } from '@pascal-app/core/schema';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { DESTRUCTIVE_TOOL_ANNOTATIONS, READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
|
|
7
|
+
import { refusalResult, toolError } from './errors.js';
|
|
8
|
+
import { persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
|
|
9
|
+
import { briefInForce, toPatches } from './shared-tools.js';
|
|
10
|
+
/** The kind an artifact records; a room's floor finish and a wall face's are none of the node kinds. */
|
|
11
|
+
const ARTIFACT_KIND = {
|
|
12
|
+
object: 'item',
|
|
13
|
+
window: 'window',
|
|
14
|
+
door: 'door',
|
|
15
|
+
column: 'column',
|
|
16
|
+
floor: undefined,
|
|
17
|
+
'wall-face': undefined,
|
|
18
|
+
};
|
|
19
|
+
/** Compiles a module on the host and stores its GLB and text for the scene: the step every scripted tool shares. */
|
|
20
|
+
export async function compileAndStore(host, sceneId, { code, language, params, inputs, }, kind, context = {}) {
|
|
21
|
+
const nodeId = context.nodeId ?? generateId(ARTIFACT_KIND[kind] ?? 'item');
|
|
22
|
+
const metadata = GeometryArtifactMetadata.parse({
|
|
23
|
+
...context.metadata,
|
|
24
|
+
kind: ARTIFACT_KIND[kind],
|
|
25
|
+
});
|
|
26
|
+
if (host.build)
|
|
27
|
+
return {
|
|
28
|
+
...(await host.build({ sceneId, code, language, params, inputs, kind, nodeId, metadata })),
|
|
29
|
+
nodeId,
|
|
30
|
+
};
|
|
31
|
+
const { glb, ...compiled } = await host.compile({ code, language, params, inputs });
|
|
32
|
+
metadata.mount = compiled.mount;
|
|
33
|
+
const [sha256] = await Promise.all([
|
|
34
|
+
host.storeArtifact({
|
|
35
|
+
sceneId,
|
|
36
|
+
nodeId,
|
|
37
|
+
metadata,
|
|
38
|
+
sha256: compiled.sha256,
|
|
39
|
+
bytes: glb,
|
|
40
|
+
mimeType: 'model/gltf-binary',
|
|
41
|
+
}),
|
|
42
|
+
host.storeArtifact({
|
|
43
|
+
sceneId,
|
|
44
|
+
nodeId,
|
|
45
|
+
metadata,
|
|
46
|
+
sha256: compiled.script,
|
|
47
|
+
bytes: new TextEncoder().encode(code),
|
|
48
|
+
mimeType: GEOMETRY_SCRIPT_MIME_TYPES[language],
|
|
49
|
+
}),
|
|
50
|
+
]);
|
|
51
|
+
return { ...compiled, sha256, nodeId };
|
|
52
|
+
}
|
|
53
|
+
async function scriptText(host, sceneId, node) {
|
|
54
|
+
const bytes = await host.readArtifact({ sceneId, sha256: node.source.script });
|
|
55
|
+
if (!bytes)
|
|
56
|
+
throw new Error(`The script of ${node.id} could not be read`);
|
|
57
|
+
return new TextDecoder().decode(bytes);
|
|
58
|
+
}
|
|
59
|
+
export function readScript(host, sceneId, bridge, nodeId) {
|
|
60
|
+
return scriptText(host, sceneId, authoredObject(bridge.getNodes(), nodeId));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* One object's module compiled and stored by the host: a new one from its code, an edit from its
|
|
64
|
+
* code or its stored script, with the params it keeps. The step a lone add_object and each
|
|
65
|
+
* add_object of a run_batch share.
|
|
66
|
+
*/
|
|
67
|
+
export async function compileObject(host, sceneId, bridge, args) {
|
|
68
|
+
const code = args.code ??
|
|
69
|
+
(args.nodeId ? await readScript(host, sceneId, bridge, args.nodeId) : refuseMissingCode());
|
|
70
|
+
const nodes = bridge.getNodes();
|
|
71
|
+
const previous = args.nodeId ? nodes[args.nodeId] : undefined;
|
|
72
|
+
const language = editedScriptLanguage(previous, args);
|
|
73
|
+
const params = editedScriptParams(previous, args.params);
|
|
74
|
+
return compileAndStore(host, sceneId, { code, language, params }, 'object', {
|
|
75
|
+
nodeId: args.nodeId,
|
|
76
|
+
metadata: {
|
|
77
|
+
...(isScriptedNode(previous) ? scriptedObjectMeta(previous) : {}),
|
|
78
|
+
...GeometryReuseFields.parse(args),
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/** What a batch's add_object builds with: the host's compile, on the scene open now. */
|
|
83
|
+
export async function compileObjectOnHost(host, bridge, args) {
|
|
84
|
+
if (!host)
|
|
85
|
+
refuse('scripts_unavailable', 'This Pascal server cannot run geometry scripts.');
|
|
86
|
+
const scene = bridge.getActiveScene();
|
|
87
|
+
if (!scene)
|
|
88
|
+
refuse('no_active_scene', 'Open or save a scene first: authored objects are stored with a scene.');
|
|
89
|
+
return compileObject(host, scene.id, bridge, args);
|
|
90
|
+
}
|
|
91
|
+
/** `add_object` on the MCP: the shared contract and operation, with the host's compile in front. */
|
|
92
|
+
export function registerAddObject(server, bridge, host) {
|
|
93
|
+
server.registerTool(addObjectTool.name, {
|
|
94
|
+
title: addObjectTool.title,
|
|
95
|
+
description: addObjectTool.description,
|
|
96
|
+
inputSchema: z.object(addObjectTool.input),
|
|
97
|
+
annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
|
|
98
|
+
}, async (input) => {
|
|
99
|
+
const brief = briefInForce(bridge);
|
|
100
|
+
if (brief !== undefined) {
|
|
101
|
+
const refusal = furnishingRefusal(addObjectTool.name, input, brief);
|
|
102
|
+
if (refusal)
|
|
103
|
+
return refusalResult(refusal);
|
|
104
|
+
}
|
|
105
|
+
if (!host) {
|
|
106
|
+
return toolError('This Pascal server cannot run geometry scripts.', {
|
|
107
|
+
code: 'scripts_unavailable',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const scene = bridge.getActiveScene();
|
|
111
|
+
if (!scene) {
|
|
112
|
+
return toolError('Open or save a scene first: authored objects are stored with a scene.', {
|
|
113
|
+
code: 'no_active_scene',
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
const args = input;
|
|
117
|
+
let compiled;
|
|
118
|
+
try {
|
|
119
|
+
requireAddObjectReason(args);
|
|
120
|
+
compiled = await compileObject(host, scene.id, bridge, args);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (isAgentRefusal(error))
|
|
124
|
+
return refusalResult(error);
|
|
125
|
+
return toolError(`${error instanceof Error ? error.message : String(error)} ${CATALOG_SOURCE}`, { code: 'script_failed' });
|
|
126
|
+
}
|
|
127
|
+
// A copy: the hosted bridge writes its map in place, and a "before" that grows with the call
|
|
128
|
+
// reads every creation as unchanged.
|
|
129
|
+
const before = { ...bridge.getNodes() };
|
|
130
|
+
let outcome;
|
|
131
|
+
try {
|
|
132
|
+
outcome = addObject(before, { ...args, compiled }, { activeLevelId: bridge.activeLevelId?.() ?? null });
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return refusalResult(error);
|
|
136
|
+
}
|
|
137
|
+
const patches = outcome.changes ? toPatches(outcome.changes) : [];
|
|
138
|
+
if (patches.length)
|
|
139
|
+
bridge.applyPatch(patches);
|
|
140
|
+
const payload = {
|
|
141
|
+
...outcome.result,
|
|
142
|
+
// What the scene holds now, as every write answers.
|
|
143
|
+
achieved: achievedChanges(before, outcome.changes ?? {}),
|
|
144
|
+
...persistencePayload(await publishLiveSceneSnapshot(bridge, addObjectTool.name)),
|
|
145
|
+
};
|
|
146
|
+
return {
|
|
147
|
+
content: [{ type: 'text', text: JSON.stringify(payload) }],
|
|
148
|
+
structuredContent: payload,
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function refuseMissingCode() {
|
|
153
|
+
refuse('code_required', 'Pass code to build a new object; params alone rebuild an existing one (nodeId).');
|
|
154
|
+
}
|
|
155
|
+
/** `get_source` on the MCP: the object's module text, read back through the host's store. */
|
|
156
|
+
export function registerGetSource(server, bridge, host) {
|
|
157
|
+
server.registerTool(getSourceTool.name, {
|
|
158
|
+
title: getSourceTool.title,
|
|
159
|
+
description: getSourceTool.description,
|
|
160
|
+
inputSchema: z.object(getSourceTool.input),
|
|
161
|
+
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
162
|
+
}, async ({ nodeId, face }) => {
|
|
163
|
+
if (!host) {
|
|
164
|
+
return toolError('This Pascal server cannot read geometry scripts.', {
|
|
165
|
+
code: 'scripts_unavailable',
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const scene = bridge.getActiveScene();
|
|
169
|
+
if (!scene)
|
|
170
|
+
return toolError('Open a scene first.', { code: 'no_active_scene' });
|
|
171
|
+
try {
|
|
172
|
+
const node = readableScript(bridge.getNodes(), nodeId, face);
|
|
173
|
+
const payload = readSourceResult(node, await scriptText(host, scene.id, node));
|
|
174
|
+
return {
|
|
175
|
+
content: [{ type: 'text', text: JSON.stringify(payload) }],
|
|
176
|
+
structuredContent: payload,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (isAgentRefusal(error))
|
|
181
|
+
return refusalResult(error);
|
|
182
|
+
return toolError(error instanceof Error ? error.message : String(error), {
|
|
183
|
+
code: 'script_unreadable',
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/tools/annotations.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B
|
|
1
|
+
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/tools/annotations.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B;aACrC,YAAY;aACZ,eAAe;aACf,cAAc;aACd,aAAa;CACL,CAAA;AAEV,eAAO,MAAM,qCAAqC;aAChD,YAAY;aACZ,eAAe;aACf,cAAc;aACd,aAAa;CACL,CAAA;AAEV,eAAO,MAAM,yBAAyB;aACpC,YAAY;aACZ,eAAe;aACf,aAAa;CACL,CAAA;AAEV,eAAO,MAAM,4BAA4B;aACvC,YAAY;aACZ,eAAe;aACf,aAAa;CACL,CAAA;AAEV,eAAO,MAAM,uCAAuC;aAClD,YAAY;aACZ,eAAe;aACf,aAAa;CACL,CAAA"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/server';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import type { SceneOperations } from '../operations/index.js';
|
|
4
|
+
import './honest-patch-guard.js';
|
|
5
|
+
import './level-height-guard.js';
|
|
6
|
+
import './roof-level-guard.js';
|
|
4
7
|
export declare const applyPatchInput: {
|
|
5
8
|
patches: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
6
9
|
op: z.ZodLiteral<"create">;
|
|
@@ -17,16 +20,20 @@ export declare const applyPatchInput: {
|
|
|
17
20
|
}, z.core.$strip>], "op">>;
|
|
18
21
|
};
|
|
19
22
|
export declare const applyPatchOutput: {
|
|
23
|
+
project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
24
|
+
unsaved: z.ZodOptional<z.ZodString>;
|
|
20
25
|
persistence: z.ZodOptional<z.ZodObject<{
|
|
21
26
|
status: z.ZodEnum<{
|
|
22
|
-
unbound: "unbound";
|
|
23
27
|
events_unsupported: "events_unsupported";
|
|
28
|
+
unbound: "unbound";
|
|
24
29
|
}>;
|
|
25
30
|
warning: z.ZodString;
|
|
26
31
|
}, z.core.$strip>>;
|
|
27
32
|
appliedOps: z.ZodNumber;
|
|
28
33
|
deletedIds: z.ZodArray<z.ZodString>;
|
|
29
34
|
createdIds: z.ZodArray<z.ZodString>;
|
|
35
|
+
/** What the server changed in the patch before writing it, one line each. */
|
|
36
|
+
notes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
30
37
|
};
|
|
31
38
|
export declare function registerApplyPatch(server: McpServer, bridge: SceneOperations): void;
|
|
32
39
|
//# sourceMappingURL=apply-patch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-patch.d.ts","sourceRoot":"","sources":["../../src/tools/apply-patch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"apply-patch.d.ts","sourceRoot":"","sources":["../../src/tools/apply-patch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,OAAO,sBAAsB,CAAA;AAC7B,OAAO,sBAAsB,CAAA;AAC7B,OAAO,oBAAoB,CAAA;AAK3B,eAAO,MAAM,eAAe;IAC1B,OAAO;;;;;;;;;;;;;CACR,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;IAI3B,6EAA6E;;CAG9E,CAAA;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAgFnF"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import { isAgentRefusal } from '@pascal-app/core/agent-tools';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
import { DESTRUCTIVE_TOOL_ANNOTATIONS } from './annotations.js';
|
|
3
|
-
import {
|
|
4
|
+
import { ProtocolError, ProtocolErrorCode, refusalResult, throwMcpError } from './errors.js';
|
|
5
|
+
import './honest-patch-guard.js';
|
|
6
|
+
import './level-height-guard.js';
|
|
7
|
+
import './roof-level-guard.js';
|
|
4
8
|
import { liveSyncOutput, persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
|
|
9
|
+
import { assertPatchKeepsIdentity, PatchRefusedError, runPatchGuards } from './patch-guards.js';
|
|
5
10
|
import { PatchSchema } from './schemas.js';
|
|
6
11
|
export const applyPatchInput = {
|
|
7
12
|
patches: z.array(PatchSchema),
|
|
@@ -10,14 +15,16 @@ export const applyPatchOutput = {
|
|
|
10
15
|
appliedOps: z.number(),
|
|
11
16
|
deletedIds: z.array(z.string()),
|
|
12
17
|
createdIds: z.array(z.string()),
|
|
18
|
+
/** What the server changed in the patch before writing it, one line each. */
|
|
19
|
+
notes: z.array(z.string()).optional(),
|
|
13
20
|
...liveSyncOutput,
|
|
14
21
|
};
|
|
15
22
|
export function registerApplyPatch(server, bridge) {
|
|
16
23
|
server.registerTool('apply_patch', {
|
|
17
24
|
title: 'Apply patch',
|
|
18
|
-
description:
|
|
19
|
-
inputSchema: applyPatchInput,
|
|
20
|
-
outputSchema: applyPatchOutput,
|
|
25
|
+
description: "Apply a batch of create/update/delete operations atomically. All patches are validated before any are applied; the entire batch forms a single undo step. Batch-first is the default: prefer one apply_patch call containing all create/update/delete ops for a build step, in stable order so later ops can reference ids created by earlier ops. A single call is atomic (all or nothing) and pays the snapshot and save cost once; do not loop one-op calls. A create whose id already exists fails the whole patch with node_exists; to replace a node, delete it earlier in the same patch. An update cannot change id or type (identity_change) or object or children (immutable_field); restating the current value is fine. A parentId change must name an existing node that holds children (invalid_parent). An update cannot add schema issues to a node (invalid_update). After a delete or a roof update that regenerates a roof's default gutters, those gutters and their downspouts are addressable only in a later call (regenerated_default). A roof created or moved onto the storey whose walls carry it goes to the level above them (the roof level over a top storey), said in notes; storey content (walls, zones, slabs, ceilings, items, stairs) on a roof level (roof_level), a walled level declared the roof level (roof_level_holds_storey) and floor indexes putting a roof level under a storey (roof_level_on_top) are refused. Refusals come back as a tool error whose text is JSON {code, patchIndex, id, message}.",
|
|
26
|
+
inputSchema: z.object(applyPatchInput),
|
|
27
|
+
outputSchema: z.object(applyPatchOutput),
|
|
21
28
|
annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
|
|
22
29
|
}, async ({ patches }) => {
|
|
23
30
|
const bridgePatches = patches.map((p) => {
|
|
@@ -42,12 +49,17 @@ export function registerApplyPatch(server, bridge) {
|
|
|
42
49
|
};
|
|
43
50
|
});
|
|
44
51
|
try {
|
|
52
|
+
const notes = runPatchGuards(bridgePatches, bridge.getNodes());
|
|
53
|
+
const planDeletion = bridge
|
|
54
|
+
.planDeletion;
|
|
55
|
+
assertPatchKeepsIdentity(bridgePatches, bridge.getNodes(), bridge.getRootNodeIds(), typeof planDeletion === 'function' ? planDeletion.bind(bridge) : undefined);
|
|
45
56
|
const result = bridge.applyPatch(bridgePatches);
|
|
46
57
|
const persistence = await publishLiveSceneSnapshot(bridge, 'apply_patch');
|
|
47
58
|
const payload = {
|
|
48
59
|
appliedOps: result.appliedOps,
|
|
49
60
|
deletedIds: result.deletedIds,
|
|
50
61
|
createdIds: result.createdIds,
|
|
62
|
+
...(notes.length ? { notes } : {}),
|
|
51
63
|
...persistencePayload(persistence),
|
|
52
64
|
};
|
|
53
65
|
return {
|
|
@@ -56,8 +68,27 @@ export function registerApplyPatch(server, bridge) {
|
|
|
56
68
|
};
|
|
57
69
|
}
|
|
58
70
|
catch (err) {
|
|
71
|
+
if (err instanceof PatchRefusedError) {
|
|
72
|
+
// A tool error, not an ProtocolError: the SDK keeps only an ProtocolError's
|
|
73
|
+
// message, and clients need the code, index and id to act on it.
|
|
74
|
+
const refusal = {
|
|
75
|
+
code: err.code,
|
|
76
|
+
patchIndex: err.patchIndex,
|
|
77
|
+
id: err.nodeId,
|
|
78
|
+
message: err.message,
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
content: [{ type: 'text', text: JSON.stringify(refusal) }],
|
|
82
|
+
isError: true,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// A refusal the store made (an accidental wipe) answers with its code, as the shared tools'.
|
|
86
|
+
if (isAgentRefusal(err))
|
|
87
|
+
return refusalResult(err);
|
|
88
|
+
if (err instanceof ProtocolError)
|
|
89
|
+
throw err;
|
|
59
90
|
const msg = err instanceof Error ? err.message : String(err);
|
|
60
|
-
throwMcpError(
|
|
91
|
+
throwMcpError(ProtocolErrorCode.InvalidParams, msg);
|
|
61
92
|
}
|
|
62
93
|
});
|
|
63
94
|
}
|
|
@@ -8,9 +8,13 @@ import type { AssetInput } from '@pascal-app/core/schema';
|
|
|
8
8
|
* common AI-generated residential layouts.
|
|
9
9
|
*/
|
|
10
10
|
export declare const MCP_CATALOG_ITEMS: AssetInput[];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
/**
|
|
12
|
+
* The items search_assets, place_items and furnish_room draw from. A host passes its own (the hosted
|
|
13
|
+
* app: its published library, as the chat searches); a standalone server keeps the built-in list.
|
|
14
|
+
*/
|
|
15
|
+
export type AssetCatalog = () => Promise<readonly AssetInput[]>;
|
|
16
|
+
export declare const builtInCatalog: AssetCatalog;
|
|
17
|
+
/** A host's catalog, read once by the first call that needs it; a failed read is tried again. */
|
|
18
|
+
export declare function cachedCatalog(load: AssetCatalog): AssetCatalog;
|
|
19
|
+
export declare function findCatalogItem(items: readonly AssetInput[], id: string): AssetInput | undefined;
|
|
16
20
|
//# sourceMappingURL=asset-catalog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-catalog.d.ts","sourceRoot":"","sources":["../../src/tools/asset-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEzD;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"asset-catalog.d.ts","sourceRoot":"","sources":["../../src/tools/asset-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEzD;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAAU,EAoTzC,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAA;AAE/D,eAAO,MAAM,cAAc,EAAE,YAA4C,CAAA;AAEzE,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,CAO9D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAEhG"}
|
|
@@ -10,6 +10,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
10
10
|
{
|
|
11
11
|
id: 'double-bed',
|
|
12
12
|
category: 'furniture',
|
|
13
|
+
functionTags: ['double-beds'],
|
|
13
14
|
tags: ['floor', 'bedroom'],
|
|
14
15
|
name: 'Double Bed',
|
|
15
16
|
thumbnail: '/items/double-bed/thumbnail.webp',
|
|
@@ -22,6 +23,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
22
23
|
{
|
|
23
24
|
id: 'single-bed',
|
|
24
25
|
category: 'furniture',
|
|
26
|
+
functionTags: ['single-beds'],
|
|
25
27
|
tags: ['floor', 'bedroom'],
|
|
26
28
|
name: 'Single Bed',
|
|
27
29
|
thumbnail: '/items/single-bed/thumbnail.webp',
|
|
@@ -34,6 +36,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
34
36
|
{
|
|
35
37
|
id: 'bedside-table',
|
|
36
38
|
category: 'furniture',
|
|
39
|
+
functionTags: ['coffee-tables'],
|
|
37
40
|
tags: ['floor', 'bedroom'],
|
|
38
41
|
name: 'Bedside Table',
|
|
39
42
|
thumbnail: '/items/bedside-table/thumbnail.webp',
|
|
@@ -47,6 +50,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
47
50
|
{
|
|
48
51
|
id: 'dresser',
|
|
49
52
|
category: 'furniture',
|
|
53
|
+
functionTags: ['dressers'],
|
|
50
54
|
tags: ['floor', 'storage', 'bedroom'],
|
|
51
55
|
name: 'Dresser',
|
|
52
56
|
thumbnail: '/items/dresser/thumbnail.webp',
|
|
@@ -60,6 +64,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
60
64
|
{
|
|
61
65
|
id: 'closet',
|
|
62
66
|
category: 'furniture',
|
|
67
|
+
functionTags: ['wardrobes'],
|
|
63
68
|
tags: ['floor', 'storage', 'bedroom'],
|
|
64
69
|
name: 'Closet',
|
|
65
70
|
thumbnail: '/items/closet/thumbnail.webp',
|
|
@@ -72,6 +77,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
72
77
|
{
|
|
73
78
|
id: 'sofa',
|
|
74
79
|
category: 'furniture',
|
|
80
|
+
functionTags: ['sofas'],
|
|
75
81
|
tags: ['floor', 'seating', 'living'],
|
|
76
82
|
name: 'Sofa',
|
|
77
83
|
thumbnail: '/items/sofa/thumbnail.webp',
|
|
@@ -84,6 +90,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
84
90
|
{
|
|
85
91
|
id: 'livingroom-chair',
|
|
86
92
|
category: 'furniture',
|
|
93
|
+
functionTags: ['armchairs'],
|
|
87
94
|
tags: ['floor', 'seating', 'living'],
|
|
88
95
|
name: 'Livingroom Chair',
|
|
89
96
|
thumbnail: '/items/livingroom-chair/thumbnail.webp',
|
|
@@ -96,6 +103,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
96
103
|
{
|
|
97
104
|
id: 'coffee-table',
|
|
98
105
|
category: 'furniture',
|
|
106
|
+
functionTags: ['coffee-tables'],
|
|
99
107
|
tags: ['floor', 'table', 'living'],
|
|
100
108
|
name: 'Coffee Table',
|
|
101
109
|
thumbnail: '/items/coffee-table/thumbnail.webp',
|
|
@@ -109,6 +117,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
109
117
|
{
|
|
110
118
|
id: 'tv-stand',
|
|
111
119
|
category: 'furniture',
|
|
120
|
+
functionTags: ['cabinets'],
|
|
112
121
|
tags: ['floor', 'storage', 'living'],
|
|
113
122
|
name: 'TV Stand',
|
|
114
123
|
thumbnail: '/items/tv-stand/thumbnail.webp',
|
|
@@ -122,6 +131,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
122
131
|
{
|
|
123
132
|
id: 'shelf',
|
|
124
133
|
category: 'furniture',
|
|
134
|
+
functionTags: ['shelves'],
|
|
125
135
|
tags: ['wall', 'storage'],
|
|
126
136
|
name: 'Shelf',
|
|
127
137
|
thumbnail: '/items/shelf/thumbnail.webp',
|
|
@@ -136,6 +146,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
136
146
|
{
|
|
137
147
|
id: 'dining-table',
|
|
138
148
|
category: 'furniture',
|
|
149
|
+
functionTags: ['dining-tables'],
|
|
139
150
|
tags: ['floor', 'table', 'dining'],
|
|
140
151
|
name: 'Dining Table',
|
|
141
152
|
thumbnail: '/items/dining-table/thumbnail.webp',
|
|
@@ -149,6 +160,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
149
160
|
{
|
|
150
161
|
id: 'dining-chair',
|
|
151
162
|
category: 'furniture',
|
|
163
|
+
functionTags: ['dining-chairs'],
|
|
152
164
|
tags: ['floor', 'seating', 'dining'],
|
|
153
165
|
name: 'Dining Chair',
|
|
154
166
|
thumbnail: '/items/dining-chair/thumbnail.webp',
|
|
@@ -161,6 +173,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
161
173
|
{
|
|
162
174
|
id: 'kitchen',
|
|
163
175
|
category: 'kitchen',
|
|
176
|
+
functionTags: ['cabinets'],
|
|
164
177
|
tags: ['floor', 'large', 'kitchen'],
|
|
165
178
|
name: 'Kitchen',
|
|
166
179
|
thumbnail: '/items/kitchen/thumbnail.webp',
|
|
@@ -173,6 +186,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
173
186
|
{
|
|
174
187
|
id: 'kitchen-counter',
|
|
175
188
|
category: 'kitchen',
|
|
189
|
+
functionTags: ['counters'],
|
|
176
190
|
tags: ['floor', 'large', 'storage', 'kitchen'],
|
|
177
191
|
name: 'Kitchen Counter',
|
|
178
192
|
thumbnail: '/items/kitchen-counter/thumbnail.webp',
|
|
@@ -186,6 +200,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
186
200
|
{
|
|
187
201
|
id: 'stove',
|
|
188
202
|
category: 'kitchen',
|
|
203
|
+
functionTags: ['kitchen-appliances'],
|
|
189
204
|
tags: ['floor', 'large', 'kitchen'],
|
|
190
205
|
name: 'Stove',
|
|
191
206
|
thumbnail: '/items/stove/thumbnail.webp',
|
|
@@ -198,6 +213,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
198
213
|
{
|
|
199
214
|
id: 'fridge',
|
|
200
215
|
category: 'kitchen',
|
|
216
|
+
functionTags: ['kitchen-appliances'],
|
|
201
217
|
tags: ['floor', 'large', 'kitchen'],
|
|
202
218
|
name: 'Fridge',
|
|
203
219
|
thumbnail: '/items/fridge/thumbnail.webp',
|
|
@@ -210,6 +226,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
210
226
|
{
|
|
211
227
|
id: 'toilet',
|
|
212
228
|
category: 'bathroom',
|
|
229
|
+
functionTags: ['toilets'],
|
|
213
230
|
tags: ['floor', 'large', 'bathroom'],
|
|
214
231
|
name: 'Toilet',
|
|
215
232
|
thumbnail: '/items/toilet/thumbnail.webp',
|
|
@@ -222,6 +239,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
222
239
|
{
|
|
223
240
|
id: 'bathroom-sink',
|
|
224
241
|
category: 'bathroom',
|
|
242
|
+
functionTags: ['sinks'],
|
|
225
243
|
tags: ['floor', 'large', 'bathroom'],
|
|
226
244
|
name: 'Bathroom Sink',
|
|
227
245
|
thumbnail: '/items/bathroom-sink/thumbnail.webp',
|
|
@@ -234,6 +252,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
234
252
|
{
|
|
235
253
|
id: 'shower-square',
|
|
236
254
|
category: 'bathroom',
|
|
255
|
+
functionTags: ['showers'],
|
|
237
256
|
tags: ['floor', 'large', 'bathroom'],
|
|
238
257
|
name: 'Squared Shower',
|
|
239
258
|
thumbnail: '/items/shower-square/thumbnail.webp',
|
|
@@ -246,6 +265,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
246
265
|
{
|
|
247
266
|
id: 'bathtub',
|
|
248
267
|
category: 'bathroom',
|
|
268
|
+
functionTags: ['bathtubs'],
|
|
249
269
|
tags: ['floor', 'large', 'bathroom'],
|
|
250
270
|
name: 'Bathtub',
|
|
251
271
|
thumbnail: '/items/bathtub/thumbnail.webp',
|
|
@@ -258,6 +278,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
258
278
|
{
|
|
259
279
|
id: 'washing-machine',
|
|
260
280
|
category: 'bathroom',
|
|
281
|
+
functionTags: ['laundry-appliances'],
|
|
261
282
|
tags: ['floor', 'large', 'electronics', 'laundry'],
|
|
262
283
|
name: 'Washing Machine',
|
|
263
284
|
thumbnail: '/items/washing-machine/thumbnail.webp',
|
|
@@ -270,6 +291,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
270
291
|
{
|
|
271
292
|
id: 'drying-rack',
|
|
272
293
|
category: 'bathroom',
|
|
294
|
+
functionTags: ['laundry-appliances'],
|
|
273
295
|
tags: ['floor', 'laundry'],
|
|
274
296
|
name: 'Drying Rack',
|
|
275
297
|
thumbnail: '/items/drying-rack/thumbnail.webp',
|
|
@@ -282,6 +304,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
282
304
|
{
|
|
283
305
|
id: 'coat-rack',
|
|
284
306
|
category: 'furniture',
|
|
307
|
+
functionTags: ['racks'],
|
|
285
308
|
tags: ['floor', 'storage', 'entry'],
|
|
286
309
|
name: 'Coat Rack',
|
|
287
310
|
thumbnail: '/items/coat-rack/thumbnail.webp',
|
|
@@ -292,17 +315,15 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
292
315
|
scale: [1, 1, 1],
|
|
293
316
|
},
|
|
294
317
|
];
|
|
295
|
-
export
|
|
296
|
-
|
|
318
|
+
export const builtInCatalog = async () => MCP_CATALOG_ITEMS;
|
|
319
|
+
/** A host's catalog, read once by the first call that needs it; a failed read is tried again. */
|
|
320
|
+
export function cachedCatalog(load) {
|
|
321
|
+
let items = null;
|
|
322
|
+
return () => (items ??= load().catch((error) => {
|
|
323
|
+
items = null;
|
|
324
|
+
throw error;
|
|
325
|
+
}));
|
|
297
326
|
}
|
|
298
|
-
export function
|
|
299
|
-
|
|
300
|
-
return MCP_CATALOG_ITEMS.filter((item) => {
|
|
301
|
-
if (args.category && item.category !== args.category)
|
|
302
|
-
return false;
|
|
303
|
-
const haystack = [item.id, item.name, item.category, ...(item.tags ?? [])]
|
|
304
|
-
.join(' ')
|
|
305
|
-
.toLowerCase();
|
|
306
|
-
return terms.every((term) => haystack.includes(term));
|
|
307
|
-
});
|
|
327
|
+
export function findCatalogItem(items, id) {
|
|
328
|
+
return items.find((item) => item.id === id);
|
|
308
329
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/server';
|
|
2
|
+
import type { SceneOperations } from '../operations/index.js';
|
|
3
|
+
import { type GeometryScriptHost } from './add-object.js';
|
|
4
|
+
/**
|
|
5
|
+
* `author_scene` on the MCP: every item's module compiled and stored through the host, the
|
|
6
|
+
* module and the adapter kept as the scene's provenance, the operation applied, Pascal's checks
|
|
7
|
+
* run, and the gate report answered. Replay is the same payload through the same operation.
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerAuthorScene(server: McpServer, bridge: SceneOperations, host: GeometryScriptHost | undefined): void;
|
|
10
|
+
//# sourceMappingURL=author-scene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author-scene.d.ts","sourceRoot":"","sources":["../../src/tools/author-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAe7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAevE;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,kBAAkB,GAAG,SAAS,GACnC,IAAI,CA0HN"}
|