Files
editor/packages/mcp/src/prompts/from-brief.ts
T
Wawa e618175bba Reset core/viewer/editor/mcp packages and apps/editor from private-editor
Wholesale swap of packages/{core,viewer,editor,mcp} and apps/editor with the
versions from the private editor repo, which is the production source of truth.

Setup changes:
- packages/{core,viewer,editor} versions held at 0.7.0 baseline (matching
  the most recent published release) so a bump=minor publishes 0.8.0
- packages/mcp held at 0.1.1 (never published; first publish will go through
  the new release.yml flow)
- peerDependencies and devDependencies for inter-package @pascal-app/*
  references pinned to ^0.7.0 instead of '*' / 'workspace:*' so they are
  valid for npm consumers
- Root package.json: TypeScript bumped to 6.0.2, added overrides for
  @types/react, @types/react-dom, @types/three to prevent JSX namespace
  fragmentation across the workspace
- release.yml extended to also publish editor and mcp; 'both' option renamed
  to 'all'; added a sync step that updates inter-package peerDeps/devDeps to
  match the new versions on every bump (so viewer/editor/mcp tarballs always
  reference the version of core they were built against)
- Root scripts gained release:editor and release:mcp shortcuts

Verification:
- bun install --frozen-lockfile is consistent
- packages/{core,viewer,mcp} build cleanly, dist/index.d.ts emitted
- packages/editor check-types reports 21 pre-existing errors, identical to
  what private-editor currently reports

Open PRs against editor-v2 will need rebasing/conflict resolution.
2026-05-09 20:52:26 +00:00

66 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { z } from 'zod'
import type { SceneOperations } from '../operations'
import { SCENE_DESIGN_GUIDANCE } from './scene-guidance'
const PREAMBLE = [
'You are a Pascal 3D scene designer.',
'You have access to semantic scene tools and the lower-level `apply_patch` tool. Prefer semantic construction/room/opening/furnishing tools for architectural work, and use `apply_patch` for bulk graph edits that need exact control.',
'If the user asks for a new project, call `create_project` before building. Use `create_house_from_brief` for a fast starter, then refine with semantic tools. Semantic tools update the browser-visible draft; call `save_scene` with `saveMode: "checkpoint"` only for meaningful milestones, then call `verify_scene` and `get_project_status`, and return the final `editorUrl`.',
'Build incrementally with visible progress. Starting from an empty scene, first create/load a Site and Building, then create occupied Levels and `create_story_shell` once per story before detailed rooms, openings, furniture, a dedicated roof level via `create_roof`, and landscaping.',
'Respect these invariants:',
' - Levels live under a Building.',
' - Walls, fences, zones, slabs, ceilings, roofs, stairs live under a Level.',
' - Multi-story exterior walls are per-level story walls; never make lower-level walls taller to stand in for upper-level walls.',
' - Doors and windows live under a Wall (parentId = wallId).',
' - Floor items live under a Level; wall/ceiling-attached items live under their target Wall or Ceiling. Do not place items directly under the Site node.',
'Use realistic dimensions in meters. Keep wall thickness small (0.10.3 m) and ceiling height 2.43.0 m unless the brief dictates otherwise.',
SCENE_DESIGN_GUIDANCE,
'Respond ONLY with tool calls. Do not produce verbose narrative or prose; keep any explanations in short tool-call arguments.',
].join('\n')
/**
* Build the user-facing prompt text for `from_brief`. Pure function for testability.
*/
export function buildFromBriefPrompt(args: {
brief: string
constraints?: string | undefined
}): string {
const parts: string[] = [PREAMBLE, '', '## Brief', args.brief.trim()]
if (args.constraints && args.constraints.trim().length > 0) {
parts.push('', '## Constraints', args.constraints.trim())
}
parts.push(
'',
'## Task',
'Produce tool calls that realise the brief within the stated constraints. For a new project, call create_project first. Use create_house_from_brief for a fast starter or prefer create_story_shell/create_room/add_door/add_window/create_stair_between_levels/create_roof/furnish_room for architectural layout, use apply_patch for exact bulk graph work, call save_scene with saveMode: "checkpoint" only when the design reaches a meaningful milestone, then call validate_scene, verify_scene, and get_project_status.',
)
return parts.join('\n')
}
export function registerFromBrief(server: McpServer, _bridge: SceneOperations): void {
server.registerPrompt(
'from_brief',
{
title: 'Generate a Pascal scene from a brief',
description:
'Produces a plan of apply_patch calls to create a scene from a natural-language brief.',
argsSchema: {
brief: z.string(),
constraints: z.string().optional(),
},
},
async ({ brief, constraints }) => ({
messages: [
{
role: 'user',
content: {
type: 'text',
text: buildFromBriefPrompt({ brief, constraints }),
},
},
],
}),
)
}