@a-company/atelier 0.36.0 → 0.38.0

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 (99) hide show
  1. package/dist/{chunk-JPZ4F4PW.js → chunk-3ARBOSWY.js} +64 -5
  2. package/dist/chunk-3ARBOSWY.js.map +1 -0
  3. package/dist/cli.js +11469 -413
  4. package/dist/cli.js.map +1 -1
  5. package/dist/{dist-M67UZGFQ.js → dist-3YQK6PI6.js} +2 -2
  6. package/dist/index.cjs +3193 -227
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +701 -8
  9. package/dist/index.d.ts +701 -8
  10. package/dist/index.js +7237 -72
  11. package/dist/index.js.map +1 -1
  12. package/dist/mcp.js +2898 -507
  13. package/dist/mcp.js.map +1 -1
  14. package/package.json +14 -9
  15. package/src/web/inline-app.ts +55 -4
  16. package/src/web/timeline-state-types.ts +28 -0
  17. package/src/web/timeline-view.test.ts +99 -0
  18. package/src/web/timeline-view.ts +339 -0
  19. package/src/web/workspace-app.ts +3146 -0
  20. package/templates/workspace/.claude/agents/atelier-iris.md +75 -0
  21. package/templates/workspace/.claude/agents/atelier-lux.md +67 -0
  22. package/templates/workspace/.claude/agents/atelier-quill.md +61 -0
  23. package/templates/workspace/.gitignore +30 -0
  24. package/templates/workspace/.paradigm/personas/_shared/cascade-merge.md +172 -0
  25. package/templates/workspace/CLAUDE.md +93 -0
  26. package/templates/workspace/README.md +75 -0
  27. package/templates/workspace/SETUP.md +127 -0
  28. package/templates/workspace/_brand/.atelier-brand.yaml +34 -0
  29. package/templates/workspace/_brand/DESIGN.md +56 -0
  30. package/templates/workspace/_brand/SCRIPT.md +41 -0
  31. package/templates/workspace/_brand/STORYBOARD.md +33 -0
  32. package/templates/workspace/_packs/README.md +54 -0
  33. package/templates/workspace/projects/README.md +49 -0
  34. package/templates/workspace/workspace.atelier +22 -0
  35. package/university/content/notes/N-atel-001-first-render.md +114 -0
  36. package/university/content/notes/N-atel-001-install-and-launch.md +84 -0
  37. package/university/content/notes/N-atel-001-what-is-atelier.md +51 -0
  38. package/university/content/notes/N-atel-101-easings.md +97 -0
  39. package/university/content/notes/N-atel-101-layers.md +106 -0
  40. package/university/content/notes/N-atel-101-states-and-deltas.md +94 -0
  41. package/university/content/notes/N-atel-101-the-atelier-format.md +72 -0
  42. package/university/content/notes/N-atel-201-authoring-tools.md +141 -0
  43. package/university/content/notes/N-atel-201-mcp-overview.md +86 -0
  44. package/university/content/notes/N-atel-201-patterns.md +108 -0
  45. package/university/content/notes/N-atel-201-visual-and-effects.md +125 -0
  46. package/university/content/notes/N-atel-301-composition-and-overlays.md +141 -0
  47. package/university/content/notes/N-atel-301-effects.md +136 -0
  48. package/university/content/notes/N-atel-301-images-and-video.md +126 -0
  49. package/university/content/notes/N-atel-301-shapes-and-text.md +118 -0
  50. package/university/content/notes/N-atel-401-hierarchical-states.md +71 -0
  51. package/university/content/notes/N-atel-401-motion-deep-dive.md +106 -0
  52. package/university/content/notes/N-atel-401-presets-and-templates.md +98 -0
  53. package/university/content/notes/N-atel-401-transitions.md +94 -0
  54. package/university/content/notes/N-atel-501-detected-vs-user-edited.md +76 -0
  55. package/university/content/notes/N-atel-501-layer-tag-isolation.md +62 -0
  56. package/university/content/notes/N-atel-501-silence-trim.md +98 -0
  57. package/university/content/notes/N-atel-501-transcribe-and-captions.md +98 -0
  58. package/university/content/notes/N-atel-601-carousel.md +71 -0
  59. package/university/content/notes/N-atel-601-overlay-rules.md +96 -0
  60. package/university/content/notes/N-atel-601-recipe-tools-and-apply.md +84 -0
  61. package/university/content/notes/N-atel-601-studio-recipe.md +103 -0
  62. package/university/content/notes/N-atel-701-choosing-output.md +68 -0
  63. package/university/content/notes/N-atel-701-png-and-frames.md +84 -0
  64. package/university/content/notes/N-atel-701-vector.md +85 -0
  65. package/university/content/notes/N-atel-701-video.md +88 -0
  66. package/university/content/notes/N-atel-801-editing-surface.md +69 -0
  67. package/university/content/notes/N-atel-801-live-bridge.md +84 -0
  68. package/university/content/notes/N-atel-801-studio-app.md +72 -0
  69. package/university/content/notes/N-atel-801-symbiotic-loop.md +56 -0
  70. package/university/content/paths/LP-atel-001.yaml +21 -0
  71. package/university/content/paths/LP-atel-101.yaml +22 -0
  72. package/university/content/paths/LP-atel-201.yaml +23 -0
  73. package/university/content/paths/LP-atel-301.yaml +22 -0
  74. package/university/content/paths/LP-atel-401.yaml +22 -0
  75. package/university/content/paths/LP-atel-501.yaml +22 -0
  76. package/university/content/paths/LP-atel-601.yaml +22 -0
  77. package/university/content/paths/LP-atel-701.yaml +22 -0
  78. package/university/content/paths/LP-atel-801.yaml +22 -0
  79. package/university/content/quizzes/Q-atel-001-orientation.yaml +66 -0
  80. package/university/content/quizzes/Q-atel-101-document-model.yaml +66 -0
  81. package/university/content/quizzes/Q-atel-201-mcp-authoring.yaml +66 -0
  82. package/university/content/quizzes/Q-atel-301-visual-system.yaml +66 -0
  83. package/university/content/quizzes/Q-atel-401-state-machines.yaml +66 -0
  84. package/university/content/quizzes/Q-atel-501-video-pipeline.yaml +66 -0
  85. package/university/content/quizzes/Q-atel-601-recipes.yaml +66 -0
  86. package/university/content/quizzes/Q-atel-701-export.yaml +66 -0
  87. package/university/content/quizzes/Q-atel-801-studio-loop.yaml +66 -0
  88. package/university/index.yaml +720 -0
  89. package/university/pack.yaml +21 -0
  90. package/dist/chunk-5QQESXI6.js +0 -4432
  91. package/dist/chunk-5QQESXI6.js.map +0 -1
  92. package/dist/chunk-JPZ4F4PW.js.map +0 -1
  93. package/dist/cli.cjs +0 -6313
  94. package/dist/cli.cjs.map +0 -1
  95. package/dist/cli.d.cts +0 -1
  96. package/dist/cli.d.ts +0 -1
  97. package/dist/mcp.cjs +0 -5462
  98. package/dist/mcp.cjs.map +0 -1
  99. /package/dist/{dist-M67UZGFQ.js.map → dist-3YQK6PI6.js.map} +0 -0
package/dist/mcp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../mcp/src/index.ts","../../mcp/src/store.ts","../../mcp/src/tools/document.ts","../../schema/src/units.ts","../../schema/src/coordinates.ts","../../schema/src/color.ts","../../schema/src/shape.ts","../../schema/src/easing.ts","../../schema/src/shadow.ts","../../schema/src/layer.ts","../../schema/src/interaction.ts","../../schema/src/delta.ts","../../schema/src/state.ts","../../schema/src/preset.ts","../../schema/src/variable.ts","../../schema/src/asset.ts","../../schema/src/document.ts","../../schema/src/recipe.ts","../../schema/src/validate.ts","../../schema/src/parse.ts","../../mcp/src/tools/layers.ts","../../mcp/src/tools/shapes.ts","../../mcp/src/tools/states.ts","../../mcp/src/tools/deltas.ts","../../math/src/easing.ts","../../math/src/spring.ts","../../math/src/lerp.ts","../../math/src/color.ts","../../math/src/path.ts","../../core/src/resolver/delta-resolver.ts","../../core/src/resolver/easing-resolver.ts","../../core/src/expressions/expression-evaluator.ts","../../core/src/resolver/frame-resolver.ts","../../core/src/validation/overlap-validator.ts","../../core/src/builder/document-builder.ts","../../core/src/units/resolve-units.ts","../../core/src/presets/preset-resolver.ts","../../core/src/state/state-machine.ts","../../core/src/templates/template-resolver.ts","../../core/src/audio/audio-timing.ts","../../mcp/src/tools/presets.ts","../../mcp/src/tools/preview.ts","../../mcp/src/tools/templates.ts","../../mcp/src/tools/layer-effects.ts","../../mcp/src/tools/state-config.ts","../../mcp/src/tools/export.ts","../../canvas/src/styles.ts","../../canvas/src/apply-properties.ts","../../canvas/src/renderers/shape-renderer.ts","../../canvas/src/renderers/text-renderer.ts","../../canvas/src/renderers/image-renderer.ts","../../canvas/src/renderers/video-renderer.ts","../../canvas/src/renderers/ref-renderer.ts","../../canvas/src/render-frame.ts","../../canvas/src/image-cache.ts","../../svg/src/render-svg.ts","../../svg/src/svg-properties.ts","../../svg/src/svg-gradients.ts","../../svg/src/svg-shapes.ts","../../svg/src/svg-text.ts","../../svg/src/svg-filters.ts","../../svg/src/svg-clip.ts","../../lottie/src/map-colors.ts","../../lottie/src/map-shapes.ts","../../lottie/src/map-easing.ts","../../lottie/src/map-keyframes.ts","../../lottie/src/map-layers.ts","../../lottie/src/warnings.ts","../../lottie/src/export-lottie.ts","../../mcp/src/tools/assets.ts","../../mcp/src/tools/variables.ts","../../mcp/src/tools/interactions.ts","../../mcp/src/tools/refs.ts","../../mcp/src/tools/performance.ts","../../mcp/src/tools/overlays.ts","../../mcp/src/tools/recipes.ts","../../mcp/src/tools/import-images.ts","../../mcp/src/bridge-protocol.ts","../../mcp/src/transports/ws-transport.ts"],"sourcesContent":["// @a-company/atelier-mcp — MCP server: AI authoring interface for animations\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { DocumentStore } from \"./store.js\";\nimport { register as registerDocumentTools } from \"./tools/document.js\";\nimport { register as registerLayerTools } from \"./tools/layers.js\";\nimport { register as registerShapeTools } from \"./tools/shapes.js\";\nimport { register as registerStateTools } from \"./tools/states.js\";\nimport { register as registerDeltaTools } from \"./tools/deltas.js\";\nimport { register as registerPresetTools } from \"./tools/presets.js\";\nimport { register as registerPreviewTools } from \"./tools/preview.js\";\nimport { register as registerTemplateTools } from \"./tools/templates.js\";\nimport { register as registerLayerEffectTools } from \"./tools/layer-effects.js\";\nimport { register as registerStateConfigTools } from \"./tools/state-config.js\";\nimport { register as registerExportTools } from \"./tools/export.js\";\nimport { register as registerAssetTools } from \"./tools/assets.js\";\nimport { register as registerVariableTools } from \"./tools/variables.js\";\nimport { register as registerInteractionTools } from \"./tools/interactions.js\";\nimport { register as registerRefTools } from \"./tools/refs.js\";\nimport { register as registerPerformanceTools } from \"./tools/performance.js\";\nimport { register as registerOverlayTools } from \"./tools/overlays.js\";\nimport { register as registerRecipeTools } from \"./tools/recipes.js\";\nimport { register as registerImportImageTools } from \"./tools/import-images.js\";\n\nexport { DocumentStore } from \"./store.js\";\nexport type { MutationSource, ChangeListener } from \"./store.js\";\nexport {\n BRIDGE_PROTOCOL_VERSION,\n isBridgeEnvelope,\n} from \"./bridge-protocol.js\";\nexport type {\n BridgeEnvelope,\n HelloEnvelope,\n DocLoadEnvelope,\n DocLoadedEnvelope,\n DocPatchEnvelope,\n LlmMutationEnvelope,\n ErrorEnvelope,\n} from \"./bridge-protocol.js\";\nexport { WebSocketServerTransport } from \"./transports/ws-transport.js\";\nexport type { WsLike } from \"./transports/ws-transport.js\";\nexport { register as registerDocumentTools } from \"./tools/document.js\";\nexport { register as registerLayerTools } from \"./tools/layers.js\";\nexport { register as registerShapeTools } from \"./tools/shapes.js\";\nexport { register as registerStateTools } from \"./tools/states.js\";\nexport { register as registerDeltaTools } from \"./tools/deltas.js\";\nexport { register as registerPresetTools } from \"./tools/presets.js\";\nexport { register as registerPreviewTools } from \"./tools/preview.js\";\nexport { register as registerTemplateTools } from \"./tools/templates.js\";\nexport { register as registerLayerEffectTools } from \"./tools/layer-effects.js\";\nexport { register as registerStateConfigTools } from \"./tools/state-config.js\";\nexport { register as registerExportTools } from \"./tools/export.js\";\nexport { register as registerAssetTools } from \"./tools/assets.js\";\nexport { register as registerVariableTools } from \"./tools/variables.js\";\nexport { register as registerInteractionTools } from \"./tools/interactions.js\";\nexport { register as registerRefTools } from \"./tools/refs.js\";\nexport { register as registerPerformanceTools } from \"./tools/performance.js\";\nexport { register as registerOverlayTools } from \"./tools/overlays.js\";\nexport { register as registerRecipeTools } from \"./tools/recipes.js\";\nexport { register as registerImportImageTools } from \"./tools/import-images.js\";\n\n/**\n * Create a fully configured MCP server with all Atelier tools registered.\n * Returns both the server and the backing store for testing.\n *\n * The `store` parameter is optional — pass an existing `DocumentStore` to\n * share state across multiple MCP server instances. This is how the\n * `atelier studio` command's per-connection WebSocket MCP servers all\n * surface their writes through a single `onChange` emitter that the live\n * bridge subscribes to (task #10).\n */\nexport function createServer(\n store: DocumentStore = new DocumentStore(),\n): { server: McpServer; store: DocumentStore } {\n\n const server = new McpServer(\n { name: \"atelier\", version: \"0.1.0\" },\n { capabilities: { tools: {} } },\n );\n\n registerDocumentTools(server, store);\n registerLayerTools(server, store);\n registerShapeTools(server, store);\n registerStateTools(server, store);\n registerDeltaTools(server, store);\n registerPresetTools(server, store);\n registerPreviewTools(server, store);\n registerTemplateTools(server, store);\n registerLayerEffectTools(server, store);\n registerStateConfigTools(server, store);\n registerExportTools(server, store);\n registerAssetTools(server, store);\n registerVariableTools(server, store);\n registerInteractionTools(server, store);\n registerRefTools(server, store);\n registerPerformanceTools(server, store);\n registerOverlayTools(server, store);\n registerRecipeTools(server, store);\n registerImportImageTools(server, store);\n\n return { server, store };\n}\n\n// ── Main entry point ─────────────────────────────────────────\n// When run directly, connect via stdio transport.\nconst isMain =\n typeof process !== \"undefined\" &&\n process.argv[1] &&\n (process.argv[1].endsWith(\"/index.js\") ||\n process.argv[1].endsWith(\"/index.cjs\") ||\n process.argv[1].includes(\"atelier-mcp\"));\n\nif (isMain) {\n const { server } = createServer();\n const transport = new StdioServerTransport();\n server.connect(transport).catch((error) => {\n console.error(\"Failed to start Atelier MCP server:\", error);\n process.exit(1);\n });\n}\n","// @a-company/atelier-mcp — In-memory document store\n\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\n\nlet counter = 0;\n\nfunction generateId(): string {\n counter++;\n return `doc_${Date.now()}_${counter}`;\n}\n\n/**\n * Source of a mutation — distinguishes who triggered the change so listeners\n * (notably the live WS bridge in task #10) can avoid echoing changes back to\n * the originator and creating a feedback loop.\n */\nexport type MutationSource = \"human\" | \"llm\" | \"system\";\n\n/**\n * Listener invoked after every mutating store operation.\n *\n * @param id The document ID that changed.\n * @param doc The new document value, or `null` if the document was deleted.\n * @param source Who triggered the change. Defaults to \"system\" when the caller\n * did not tag the mutation.\n */\nexport type ChangeListener = (\n id: string,\n doc: AtelierDocument | null,\n source: MutationSource,\n) => void;\n\n/**\n * In-memory store for AtelierDocuments.\n * Each document is keyed by a string ID.\n *\n * Supports an `onChange` event-emitter API so external observers (e.g. the\n * forthcoming WS bridge for the LLM↔human live-mutation loop — see task #10)\n * can subscribe to mutations and ferry them to other processes.\n */\nexport class DocumentStore {\n private docs = new Map<string, AtelierDocument>();\n private listeners: ChangeListener[] = [];\n\n /** Create a new document entry. Returns the assigned ID. */\n create(doc: AtelierDocument, id?: string, source: MutationSource = \"system\"): string {\n const docId = id ?? generateId();\n if (this.docs.has(docId)) {\n throw new Error(`Document \"${docId}\" already exists`);\n }\n this.docs.set(docId, doc);\n this.emit(docId, doc, source);\n return docId;\n }\n\n /** Get a document by ID. */\n get(id: string): AtelierDocument | undefined {\n return this.docs.get(id);\n }\n\n /** Set (overwrite) a document by ID. */\n set(id: string, doc: AtelierDocument, source: MutationSource = \"system\"): void {\n this.docs.set(id, doc);\n this.emit(id, doc, source);\n }\n\n /** Delete a document by ID. Returns true if it existed. */\n delete(id: string, source: MutationSource = \"system\"): boolean {\n const existed = this.docs.delete(id);\n if (existed) this.emit(id, null, source);\n return existed;\n }\n\n /** Check if a document exists. */\n has(id: string): boolean {\n return this.docs.has(id);\n }\n\n /** List all document IDs and their names. */\n list(): Array<{ id: string; name: string; canvas: AtelierDocument[\"canvas\"] }> {\n const result: Array<{ id: string; name: string; canvas: AtelierDocument[\"canvas\"] }> = [];\n for (const [id, doc] of this.docs) {\n result.push({ id, name: doc.name, canvas: doc.canvas });\n }\n return result;\n }\n\n /** Clear all documents (useful for testing). Does NOT fire onChange. */\n clear(): void {\n this.docs.clear();\n }\n\n /**\n * Subscribe to mutation events. The listener is invoked after every\n * create()/set()/delete() with the changed document ID, the new value\n * (or `null` when deleted), and the source tag.\n *\n * Returns an unsubscribe function. Multiple listeners are supported and\n * delivered in registration order. A listener that throws is isolated —\n * the error is swallowed and remaining listeners still fire.\n *\n * TODO(#10): the live WS bridge will subscribe here to forward LLM-side\n * mutations into the in-browser Studio (which exposes the symmetric\n * `AtelierStudio.applyMutation()` API).\n */\n onChange(listener: ChangeListener): () => void {\n this.listeners.push(listener);\n return () => {\n const idx = this.listeners.indexOf(listener);\n if (idx !== -1) this.listeners.splice(idx, 1);\n };\n }\n\n private emit(id: string, doc: AtelierDocument | null, source: MutationSource): void {\n // Snapshot the list so a listener mutating subscriptions mid-emit doesn't\n // skip or double-fire siblings.\n const snapshot = this.listeners.slice();\n for (const listener of snapshot) {\n try {\n listener(id, doc, source);\n } catch {\n // Isolate listener failures — one buggy subscriber must not break the\n // mutation chain for the rest. No logger is wired into this package\n // today; if/when one lands, surface the error here.\n }\n }\n }\n}\n","// @a-company/atelier-mcp — Document management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { validateDocument, parseAtelier, serializeAtelier } from \"@a-company/atelier-schema\";\nimport type { DocumentStore } from \"../store.js\";\n\n/** Helper: get document or return error result */\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_create ──────────────────────────────────────────\n server.tool(\n \"atelier_create\",\n \"Create a new Atelier animation document with canvas settings\",\n {\n name: z.string().describe(\"Animation name\"),\n width: z.number().positive().describe(\"Canvas width in pixels\"),\n height: z.number().positive().describe(\"Canvas height in pixels\"),\n fps: z.number().positive().int().describe(\"Frames per second\"),\n background: z.string().optional().describe(\"Background color (hex string)\"),\n description: z.string().optional().describe(\"Animation description\"),\n tags: z.array(z.string()).optional().describe(\"Tags for categorization\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ name, width, height, fps, background, description, tags }) => {\n const doc: AtelierDocument = {\n version: \"1.0\",\n name,\n canvas: { width, height, fps, ...(background ? { background } : {}) },\n layers: [],\n states: {},\n ...(description ? { description } : {}),\n ...(tags ? { tags } : {}),\n };\n\n const validation = validateDocument(doc);\n if (!validation.success) {\n return err(`Validation failed: ${validation.errors.map(e => `${e.path}: ${e.message}`).join(\"; \")}`);\n }\n\n const id = store.create(doc);\n return ok({ id, name: doc.name, canvas: doc.canvas });\n },\n );\n\n // ── atelier_info ────────────────────────────────────────────\n server.tool(\n \"atelier_info\",\n \"Get summary information about an Atelier document\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const stateNames = Object.keys(doc.states);\n const totalDuration = stateNames.reduce(\n (sum, name) => sum + doc.states[name].duration,\n 0,\n );\n\n return ok({\n name: doc.name,\n description: doc.description,\n tags: doc.tags,\n canvas: doc.canvas,\n layerCount: doc.layers.length,\n stateNames,\n totalDuration,\n presetNames: doc.presets ? Object.keys(doc.presets) : [],\n });\n },\n );\n\n // ── atelier_load ────────────────────────────────────────────\n server.tool(\n \"atelier_load\",\n \"Load an Atelier document from a YAML string\",\n {\n id: z.string().optional().describe(\"Custom document ID (auto-generated if omitted)\"),\n yaml: z.string().describe(\"YAML string representing an Atelier document\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, yaml }) => {\n const parsed = parseAtelier(yaml);\n if (!parsed.success) {\n return err(`Parse/validation failed: ${parsed.errors.map(e => `${e.path}: ${e.message}`).join(\"; \")}`);\n }\n\n const docId = store.create(parsed.data, id);\n return ok({ id: docId, name: parsed.data.name });\n },\n );\n\n // ── atelier_export ──────────────────────────────────────────\n server.tool(\n \"atelier_export\",\n \"Export an Atelier document as a YAML string\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n\n const yaml = serializeAtelier(result.doc);\n return { content: [{ type: \"text\" as const, text: yaml }] };\n },\n );\n\n // ── atelier_list ────────────────────────────────────────────\n server.tool(\n \"atelier_list\",\n \"List all Atelier documents in the store\",\n {},\n { readOnlyHint: true, destructiveHint: false },\n async () => {\n const docs = store.list();\n return ok({ documents: docs, count: docs.length });\n },\n );\n}\n","import { z } from \"zod\";\n\n/** Pixel value — any number */\nexport const PixelSchema = z.number();\n\n/** Percentage string like \"50%\" */\nexport const PercentageSchema = z.string().regex(/^-?\\d+(\\.\\d+)?%$/, {\n message: \"Percentage must be a number followed by %, e.g. \\\"50%\\\"\",\n});\n\n/** Either pixel or percentage */\nexport const UnitValueSchema = z.union([PixelSchema, PercentageSchema]);\n","import { z } from \"zod\";\nimport { UnitValueSchema } from \"./units.js\";\n\nexport const FrameSchema = z.object({\n x: UnitValueSchema,\n y: UnitValueSchema,\n});\n\nexport const BoundsSchema = z.object({\n width: UnitValueSchema,\n height: UnitValueSchema,\n});\n\nexport const AnchorPointSchema = z.object({\n x: z.number().min(0).max(1),\n y: z.number().min(0).max(1),\n});\n","import { z } from \"zod\";\n\nexport const RGBAColorSchema = z.object({\n r: z.number().min(0).max(255),\n g: z.number().min(0).max(255),\n b: z.number().min(0).max(255),\n a: z.number().min(0).max(1),\n});\n\nexport const HSLAColorSchema = z.object({\n h: z.number().min(0).max(360),\n s: z.number().min(0).max(100),\n l: z.number().min(0).max(100),\n a: z.number().min(0).max(1),\n});\n\nexport const HexColorSchema = z.string().regex(/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/, {\n message: \"Color must be a hex string: #RGB, #RGBA, #RRGGBB, or #RRGGBBAA\",\n});\n\nexport const ColorSchema = z.union([RGBAColorSchema, HSLAColorSchema, HexColorSchema]);\n","import { z } from \"zod\";\nimport { ColorSchema } from \"./color.js\";\nimport { UnitValueSchema } from \"./units.js\";\n\nexport const PathPointSchema = z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n});\n\nexport const RectShapeSchema = z.object({\n type: z.literal(\"rect\"),\n cornerRadius: z.union([\n z.number().min(0),\n z.tuple([z.number().min(0), z.number().min(0), z.number().min(0), z.number().min(0)]),\n ]).optional(),\n});\n\nexport const EllipseShapeSchema = z.object({\n type: z.literal(\"ellipse\"),\n});\n\nexport const PathShapeSchema = z.object({\n type: z.literal(\"path\"),\n points: z.array(PathPointSchema).min(2, \"Path must have at least 2 points\"),\n closed: z.boolean().optional(),\n});\n\nexport const ShapeSchema = z.discriminatedUnion(\"type\", [\n RectShapeSchema,\n EllipseShapeSchema,\n PathShapeSchema,\n]);\n\nexport const GradientStopSchema = z.object({\n offset: z.number().min(0).max(1),\n color: ColorSchema,\n});\n\nexport const SolidFillSchema = z.object({\n type: z.literal(\"solid\"),\n color: ColorSchema,\n});\n\nexport const LinearGradientFillSchema = z.object({\n type: z.literal(\"linear-gradient\"),\n angle: z.number(),\n stops: z.array(GradientStopSchema).min(2, \"Gradient needs at least 2 stops\"),\n});\n\nexport const RadialGradientFillSchema = z.object({\n type: z.literal(\"radial-gradient\"),\n center: z.object({ x: UnitValueSchema, y: UnitValueSchema }),\n radius: UnitValueSchema,\n stops: z.array(GradientStopSchema).min(2, \"Gradient needs at least 2 stops\"),\n});\n\nexport const FillSchema = z.discriminatedUnion(\"type\", [\n SolidFillSchema,\n LinearGradientFillSchema,\n RadialGradientFillSchema,\n]);\n\nexport const StrokeSchema = z.object({\n color: ColorSchema,\n width: z.number().min(0),\n dash: z.array(z.number().min(0)).optional(),\n lineCap: z.enum([\"butt\", \"round\", \"square\"]).optional(),\n lineJoin: z.enum([\"miter\", \"round\", \"bevel\"]).optional(),\n strokeStart: z.number().min(0).max(1).optional(),\n strokeEnd: z.number().min(0).max(1).optional(),\n});\n\nexport const TextStyleSchema = z.object({\n fontFamily: z.string().min(1, \"fontFamily is required\"),\n fontSize: z.number().positive(\"fontSize must be positive\"),\n fontWeight: z.union([z.number(), z.enum([\"normal\", \"bold\"])]).optional(),\n fontStyle: z.enum([\"normal\", \"italic\"]).optional(),\n textAlign: z.enum([\"left\", \"center\", \"right\"]).optional(),\n lineHeight: z.number().positive().optional(),\n letterSpacing: z.number().optional(),\n color: ColorSchema,\n});\n","import { z } from \"zod\";\n\nexport const LinearEasingSchema = z.object({ type: z.literal(\"linear\") });\n\nexport const CubicBezierEasingSchema = z.object({\n type: z.literal(\"cubic-bezier\"),\n x1: z.number().min(0).max(1),\n y1: z.number(),\n x2: z.number().min(0).max(1),\n y2: z.number(),\n});\n\nexport const SpringEasingSchema = z.object({\n type: z.literal(\"spring\"),\n mass: z.number().positive().optional(),\n stiffness: z.number().positive().optional(),\n damping: z.number().positive().optional(),\n velocity: z.number().optional(),\n});\n\nexport const StepEasingSchema = z.object({\n type: z.literal(\"step\"),\n steps: z.number().int().positive(),\n position: z.enum([\"start\", \"end\"]).optional(),\n});\n\nexport const EasingPresetSchema = z.enum([\"linear\", \"ease-in\", \"ease-out\", \"ease-in-out\"]);\n\nexport const EasingSchema = z.union([\n LinearEasingSchema,\n CubicBezierEasingSchema,\n SpringEasingSchema,\n StepEasingSchema,\n EasingPresetSchema,\n]);\n","import { z } from \"zod\";\nimport { ColorSchema } from \"./color.js\";\n\nexport const ShadowSchema = z.object({\n color: ColorSchema,\n blur: z.number().min(0),\n offsetX: z.number().optional(),\n offsetY: z.number().optional(),\n});\n","import { z } from \"zod\";\nimport { ShapeSchema, FillSchema, StrokeSchema, TextStyleSchema, PathPointSchema } from \"./shape.js\";\nimport { FrameSchema, BoundsSchema, AnchorPointSchema } from \"./coordinates.js\";\nimport { ShadowSchema } from \"./shadow.js\";\nimport { InteractionSchema } from \"./interaction.js\";\n\nexport const BlendModeSchema = z.enum([\n \"normal\", \"multiply\", \"screen\", \"overlay\",\n \"darken\", \"lighten\", \"color-dodge\", \"color-burn\",\n \"hard-light\", \"soft-light\", \"difference\", \"exclusion\",\n \"hue\", \"saturation\", \"color\", \"luminosity\",\n]);\n\nexport const MotionPathSchema = z.object({\n points: z.array(PathPointSchema).min(2, \"Motion path must have at least 2 points\"),\n closed: z.boolean().optional(),\n autoRotate: z.boolean().optional(),\n autoRotateOffset: z.number().optional(),\n});\n\nexport const ShapeVisualSchema = z.object({\n type: z.literal(\"shape\"),\n shape: ShapeSchema,\n fill: FillSchema.optional(),\n stroke: StrokeSchema.optional(),\n});\n\nexport const TextVisualSchema = z.object({\n type: z.literal(\"text\"),\n content: z.string(),\n style: TextStyleSchema,\n});\n\nexport const SpritesheetConfigSchema = z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n});\n\nexport const SourceRectSchema = z.object({\n x: z.number(),\n y: z.number(),\n width: z.number().positive(),\n height: z.number().positive(),\n});\n\nexport const ImageVisualSchema = z.object({\n type: z.literal(\"image\"),\n assetId: z.string().min(1, \"assetId is required\"),\n src: z.string().optional(),\n sourceRect: SourceRectSchema.optional(),\n spritesheet: SpritesheetConfigSchema.optional(),\n frameIndex: z.number().int().min(0).optional(),\n});\n\nexport const VideoVisualSchema = z.object({\n type: z.literal(\"video\"),\n assetId: z.string().min(1, \"assetId is required\"),\n src: z.string().optional(),\n startFrame: z.number().int().min(0).optional(),\n sourceOffset: z.number().min(0).optional(),\n sourceEnd: z.number().positive().optional(),\n playbackRate: z.number().positive().optional(),\n volume: z.number().min(0).max(1).optional(),\n muted: z.boolean().optional(),\n objectFit: z.enum([\"contain\", \"cover\", \"fill\"]).optional(),\n});\n\nexport const GroupVisualSchema = z.object({\n type: z.literal(\"group\"),\n});\n\nexport const RefVisualSchema = z.object({\n type: z.literal(\"ref\"),\n src: z.string().min(1, \"src is required\"),\n state: z.string().optional(),\n frame: z.number().int().min(0).optional(),\n});\n\nexport const VisualSchema = z.discriminatedUnion(\"type\", [\n ShapeVisualSchema,\n TextVisualSchema,\n ImageVisualSchema,\n VideoVisualSchema,\n GroupVisualSchema,\n RefVisualSchema,\n]);\n\nexport const LayerSchema = z.object({\n id: z.string().min(1, \"Layer id is required\"),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n visual: VisualSchema,\n frame: FrameSchema,\n bounds: BoundsSchema,\n anchorPoint: AnchorPointSchema.optional(),\n parentId: z.string().optional(),\n opacity: z.number().min(0).max(1).optional(),\n rotation: z.number().optional(),\n scale: z.object({ x: z.number(), y: z.number() }).optional(),\n visible: z.boolean().optional(),\n shadow: ShadowSchema.optional(),\n blendMode: BlendModeSchema.optional(),\n motionPath: MotionPathSchema.optional(),\n clipPath: ShapeSchema.optional(),\n tint: z.object({\n color: z.string(),\n amount: z.number().min(0).max(1),\n }).optional(),\n interactions: z.array(InteractionSchema).optional(),\n});\n","import { z } from \"zod\";\n\nexport const TriggerTypeSchema = z.enum([\n \"click\", \"hover\", \"pointerdown\", \"pointerup\", \"timer\", \"signal\",\n]);\n\nexport const TriggerSchema = z.object({\n type: TriggerTypeSchema,\n delay: z.number().nonnegative(\"Timer delay must be non-negative\").optional(),\n signal: z.string().optional(),\n}).refine(\n (t) => t.type !== \"timer\" || t.delay !== undefined,\n { message: \"Timer trigger requires a delay\" },\n).refine(\n (t) => t.type !== \"signal\" || t.signal !== undefined,\n { message: \"Signal trigger requires a signal name\" },\n);\n\nexport const ActionTypeSchema = z.enum([\n \"go-to-state\", \"emit-signal\", \"set-variable\", \"toggle-visibility\",\n]);\n\nexport const ActionSchema = z.object({\n type: ActionTypeSchema,\n state: z.string().optional(),\n signal: z.string().optional(),\n variable: z.string().optional(),\n value: z.unknown().optional(),\n targetLayer: z.string().optional(),\n}).refine(\n (a) => a.type !== \"go-to-state\" || a.state !== undefined,\n { message: \"go-to-state action requires a state name\" },\n).refine(\n (a) => a.type !== \"emit-signal\" || a.signal !== undefined,\n { message: \"emit-signal action requires a signal name\" },\n).refine(\n (a) => a.type !== \"set-variable\" || (a.variable !== undefined && a.value !== undefined),\n { message: \"set-variable action requires variable and value\" },\n);\n\nexport const InteractionSchema = z.object({\n id: z.string().min(1, \"Interaction id is required\"),\n trigger: TriggerSchema,\n action: ActionSchema,\n description: z.string().optional(),\n});\n","import { z } from \"zod\";\nimport { EasingSchema } from \"./easing.js\";\n\nexport const AnimatablePropertySchema = z.enum([\n \"frame.x\",\n \"frame.y\",\n \"bounds.width\",\n \"bounds.height\",\n \"opacity\",\n \"rotation\",\n \"scale.x\",\n \"scale.y\",\n \"anchorPoint.x\",\n \"anchorPoint.y\",\n \"visual.shape.cornerRadius\",\n \"visual.fill.color\",\n \"visual.stroke.color\",\n \"visual.stroke.width\",\n \"visual.stroke.start\",\n \"visual.stroke.end\",\n \"visual.style.fontSize\",\n \"visual.style.color\",\n \"shadow.color\",\n \"shadow.blur\",\n \"shadow.offsetX\",\n \"shadow.offsetY\",\n \"motionPath.progress\",\n \"visual.fill.angle\",\n \"visual.fill.center.x\",\n \"visual.fill.center.y\",\n \"visual.fill.radius\",\n \"visual.image.sourceRect.x\",\n \"visual.image.sourceRect.y\",\n \"visual.image.sourceRect.width\",\n \"visual.image.sourceRect.height\",\n \"visual.image.frameIndex\",\n \"visible\",\n \"tint.color\",\n \"tint.amount\",\n]);\n\nexport const FrameRangeSchema = z.tuple([\n z.number().int().min(0, \"Frame start must be >= 0\"),\n z.number().int().min(0, \"Frame end must be >= 0\"),\n]).refine(([start, end]) => end >= start, {\n message: \"Frame range end must be >= start\",\n});\n\nexport const DeltaSchema = z.object({\n id: z.string().optional(),\n name: z.string().optional(),\n layer: z.string().min(1, \"Delta must reference a layer id\"),\n property: AnimatablePropertySchema,\n range: FrameRangeSchema,\n from: z.unknown(),\n to: z.unknown(),\n easing: EasingSchema.optional(),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n});\n","import { z } from \"zod\";\nimport { DeltaSchema } from \"./delta.js\";\nimport { EasingSchema } from \"./easing.js\";\n\nexport const AudioSchema = z.object({\n src: z.string().min(1, \"Audio src is required\"),\n offset: z.number().min(0, \"Audio offset must be non-negative\").optional(),\n volume: z.number().min(0).max(1, \"Audio volume must be 0–1\").optional(),\n loop: z.boolean().optional(),\n startFrame: z.number().int().min(0, \"Audio startFrame must be a non-negative integer\").optional(),\n});\n\nexport const StateTransitionConfigSchema = z.object({\n duration: z.number().int().positive(\"Transition duration must be a positive integer (frames)\"),\n easing: EasingSchema.optional(),\n});\n\nexport const StateSchema = z.object({\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n parent: z.string().optional(),\n duration: z.number().int().positive(\"State duration must be a positive integer (frames)\"),\n deltas: z.array(DeltaSchema),\n audio: AudioSchema.optional(),\n transitions: z.record(z.string(), StateTransitionConfigSchema).optional(),\n});\n","import { z } from \"zod\";\nimport { AnimatablePropertySchema } from \"./delta.js\";\nimport { EasingSchema } from \"./easing.js\";\n\nexport const PresetDeltaSchema = z.object({\n property: AnimatablePropertySchema,\n offset: z.tuple([z.number().int().min(0), z.number().int().min(0)]).optional(),\n from: z.unknown(),\n to: z.unknown(),\n easing: EasingSchema.optional(),\n});\n\nexport const PresetSchema = z.object({\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n deltas: z.array(PresetDeltaSchema).min(1, \"Preset must have at least one delta\"),\n});\n","import { z } from \"zod\";\n\nexport const VariableTypeSchema = z.enum([\"string\", \"number\", \"color\", \"asset\", \"boolean\"]);\n\nexport const VariableSchema = z.object({\n type: VariableTypeSchema,\n default: z.unknown().optional(),\n description: z.string().optional(),\n});\n","import { z } from \"zod\";\n\nexport const AssetTypeSchema = z.enum([\"image\", \"svg\", \"font\", \"animation\", \"audio\", \"video\"]);\n\nexport const AssetSchema = z.object({\n type: AssetTypeSchema,\n src: z.string().min(1, \"Asset src is required\"),\n description: z.string().optional(),\n spritesheet: z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n }).optional(),\n videoMeta: z.object({\n duration: z.number().positive(\"videoMeta.duration must be positive\"),\n fps: z.number().positive(\"videoMeta.fps must be positive\"),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n }).optional(),\n});\n","import { z } from \"zod\";\nimport { LayerSchema } from \"./layer.js\";\nimport { StateSchema } from \"./state.js\";\nimport { PresetSchema } from \"./preset.js\";\nimport { VariableSchema } from \"./variable.js\";\nimport { AssetSchema } from \"./asset.js\";\n\nexport const CanvasSchema = z.object({\n width: z.number().int().positive(\"Canvas width must be a positive integer\"),\n height: z.number().int().positive(\"Canvas height must be a positive integer\"),\n fps: z.number().int().positive(\"FPS must be a positive integer\"),\n background: z.string().optional(),\n});\n\nexport const AtelierDocumentSchema = z.object({\n version: z.string().min(1, \"Version is required\"),\n name: z.string().min(1, \"Animation name is required\"),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n canvas: CanvasSchema,\n variables: z.record(z.string(), VariableSchema).optional(),\n assets: z.record(z.string(), AssetSchema).optional(),\n presets: z.record(z.string(), PresetSchema).optional(),\n layers: z.array(LayerSchema),\n states: z.record(z.string(), StateSchema),\n});\n","import { z } from \"zod\";\n\n/** Silence-trim policy block */\nexport const SilencePolicySchema = z.object({\n noise: z.string().optional(),\n min_silence: z.number().nonnegative().optional(),\n default_padding_pre: z.number().nonnegative().optional(),\n default_padding_post: z.number().nonnegative().optional(),\n match_tolerance: z.number().nonnegative().optional(),\n}).strict();\n\n/** Caption visual style block */\nexport const CaptionStyleSchema = z.object({\n font_family: z.string().optional(),\n font_size: z.number().positive().optional(),\n font_weight: z.union([z.literal(\"normal\"), z.literal(\"bold\"), z.number()]).optional(),\n text_align: z.enum([\"left\", \"center\", \"right\"]).optional(),\n color: z.string().optional(),\n y_ratio: z.number().min(0).max(1).optional(),\n width_ratio: z.number().min(0).max(1).optional(),\n fade_seconds: z.number().nonnegative().optional(),\n}).strict();\n\n/** Caption phrase grouping block */\nexport const CaptionGroupingSchema = z.object({\n max_words: z.number().int().positive().optional(),\n pause_gap: z.number().nonnegative().optional(),\n}).strict();\n\n/** Anchor enum shared by every overlay sub-rule */\nexport const OverlayAnchorSchema = z.enum([\n \"top-left\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-right\",\n]);\n\n/** Visual subset for overlay text — recipe snake_case convention */\nexport const OverlayTextStyleSchema = z.object({\n font_family: z.string().optional(),\n font_size: z.number().positive().optional(),\n font_weight: z.union([z.literal(\"normal\"), z.literal(\"bold\"), z.number()]).optional(),\n color: z.string().optional(),\n}).strict();\n\n/**\n * Validate a page-number format template:\n * - braces must balance\n * - every {…} group must match (current|total)(:0Nd)? (zero-pad form)\n * - at least one of {current} / {total} must appear\n *\n * Render-time substitution is a separate concern; this only validates syntax.\n */\nfunction validatePageNumberFormat(\n format: string,\n ctx: z.RefinementCtx,\n): void {\n if (format.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"format must be a non-empty string\",\n });\n return;\n }\n\n const open = (format.match(/\\{/g) ?? []).length;\n const close = (format.match(/\\}/g) ?? []).length;\n if (open !== close) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `format has unbalanced braces (${open} '{' vs ${close} '}')`,\n });\n return;\n }\n\n const groupRe = /\\{([^{}]*)\\}/g;\n const groupRule = /^(current|total)(:0\\d+d)?$/;\n let m: RegExpExecArray | null;\n let sawCurrent = false;\n let sawTotal = false;\n while ((m = groupRe.exec(format)) !== null) {\n const inner = m[1];\n if (!groupRule.test(inner)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `format placeholder \"{${inner}}\" is not recognized — expected {current}, {total}, {current:0Nd}, or {total:0Nd}`,\n });\n return;\n }\n if (inner.startsWith(\"current\")) sawCurrent = true;\n if (inner.startsWith(\"total\")) sawTotal = true;\n }\n\n if (!sawCurrent && !sawTotal) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"format must contain at least one {current} or {total} placeholder\",\n });\n }\n}\n\n/** Handle overlay rule schema — anchored creator-handle text */\nexport const OverlayHandleRuleSchema = z.object({\n text: z.string().min(1),\n anchor: OverlayAnchorSchema,\n margin: z.number().nonnegative().optional(),\n style: OverlayTextStyleSchema.optional(),\n}).strict();\n\n/** Page-number overlay rule schema — anchored \"1/5\"-style indicator */\nexport const OverlayPageNumberRuleSchema = z.object({\n format: z.string().superRefine(validatePageNumberFormat),\n anchor: OverlayAnchorSchema,\n margin: z.number().nonnegative().optional(),\n style: OverlayTextStyleSchema.optional(),\n}).strict();\n\n/** Overlay rules block (Phase 1.5) — both sub-blocks optional */\nexport const OverlayRulesSchema = z.object({\n handle: OverlayHandleRuleSchema.optional(),\n page_number: OverlayPageNumberRuleSchema.optional(),\n}).strict();\n\n/**\n * StudioRecipe — top-level. Reserved fields (caption_highlight, transition_kit,\n * etc.) still accept any shape; Phase 3 will refine them. Validate-time warnings\n * surface reserved-fields-in-use to authors so they aren't caught off-guard\n * when those sections become load-bearing.\n *\n * overlay_rules was promoted from reserved Phase 3 to first-class Phase 1.5.\n */\nexport const StudioRecipeSchema = z.object({\n version: z.string(),\n name: z.string(),\n description: z.string().optional(),\n author: z.string().optional(),\n tags: z.array(z.string()).optional(),\n\n silence_policy: SilencePolicySchema.optional(),\n caption_style: CaptionStyleSchema.optional(),\n caption_grouping: CaptionGroupingSchema.optional(),\n\n // Phase 1.5 — first-class overlay rules\n overlay_rules: OverlayRulesSchema.optional(),\n\n // Reserved — Phase 3 (parse-opaque)\n caption_highlight: z.unknown().optional(),\n transition_kit: z.unknown().optional(),\n palette: z.unknown().optional(),\n audio_policy: z.unknown().optional(),\n aspect_targets: z.array(z.unknown()).optional(),\n}).strict();\n\n/** Names of still-reserved fields — used by validators to emit forward-compat warnings */\nexport const RESERVED_RECIPE_FIELDS = [\n \"caption_highlight\",\n \"transition_kit\",\n \"palette\",\n \"audio_policy\",\n \"aspect_targets\",\n] as const;\n","import type { AtelierDocument, Layer, Delta, VideoVisual, StudioRecipe } from \"@a-company/atelier-types\";\nimport { AtelierDocumentSchema } from \"./document.js\";\nimport { LayerSchema } from \"./layer.js\";\nimport { DeltaSchema } from \"./delta.js\";\nimport { StudioRecipeSchema, RESERVED_RECIPE_FIELDS } from \"./recipe.js\";\nimport type { z } from \"zod\";\n\n/** Validation result — either success with typed data or failure with readable errors */\nexport type ValidationResult<T> =\n | { success: true; data: T }\n | { success: false; errors: ValidationError[] };\n\nexport interface ValidationError {\n path: string;\n message: string;\n}\n\n/** Format Zod errors into flat, AI-readable error messages */\nfunction formatErrors(error: z.ZodError): ValidationError[] {\n return error.issues.map((issue) => ({\n path: issue.path.join(\".\") || \"(root)\",\n message: issue.message,\n }));\n}\n\n/** Validate a complete AtelierDocument */\nexport function validateDocument(input: unknown): ValidationResult<AtelierDocument> {\n const result = AtelierDocumentSchema.safeParse(input);\n if (result.success) {\n return { success: true, data: result.data as AtelierDocument };\n }\n return { success: false, errors: formatErrors(result.error) };\n}\n\n/** Validate a single Layer */\nexport function validateLayer(input: unknown): ValidationResult<Layer> {\n const result = LayerSchema.safeParse(input);\n if (result.success) {\n return { success: true, data: result.data as Layer };\n }\n return { success: false, errors: formatErrors(result.error) };\n}\n\n/** Validate a single Delta */\nexport function validateDelta(input: unknown): ValidationResult<Delta> {\n const result = DeltaSchema.safeParse(input);\n if (result.success) {\n return { success: true, data: result.data as Delta };\n }\n return { success: false, errors: formatErrors(result.error) };\n}\n\n/**\n * Validate a VideoVisual layer against semantic constraints (^valid-video-layer gate).\n * Checks beyond Zod: sourceEnd > sourceOffset, sourceEnd ≤ videoMeta.duration.\n */\nexport function validateVideoLayer(\n visual: VideoVisual,\n videoMetaDuration?: number,\n): ValidationResult<VideoVisual> {\n const errors: ValidationError[] = [];\n\n if (!visual.assetId) {\n errors.push({ path: \"assetId\", message: \"assetId is required\" });\n }\n\n const sourceOffset = visual.sourceOffset ?? 0;\n if (visual.sourceEnd !== undefined) {\n if (visual.sourceEnd <= sourceOffset) {\n errors.push({\n path: \"sourceEnd\",\n message: `sourceEnd (${visual.sourceEnd}) must be greater than sourceOffset (${sourceOffset})`,\n });\n }\n if (videoMetaDuration !== undefined && visual.sourceEnd > videoMetaDuration) {\n errors.push({\n path: \"sourceEnd\",\n message: `sourceEnd (${visual.sourceEnd}) exceeds asset duration (${videoMetaDuration})`,\n });\n }\n }\n\n if (videoMetaDuration !== undefined && sourceOffset >= videoMetaDuration) {\n errors.push({\n path: \"sourceOffset\",\n message: `sourceOffset (${sourceOffset}) is at or beyond asset duration (${videoMetaDuration})`,\n });\n }\n\n if (errors.length > 0) return { success: false, errors };\n return { success: true, data: visual };\n}\n\n/**\n * Validate a StudioRecipe against the schema (^valid-recipe gate).\n * Returns success with the parsed recipe and optional warnings about\n * reserved-but-unimplemented Phase 3 fields that are present.\n */\nexport function validateRecipe(\n recipe: unknown,\n): ValidationResult<StudioRecipe> & { warnings?: string[] } {\n const parsed = StudioRecipeSchema.safeParse(recipe);\n if (!parsed.success) {\n return { success: false, errors: formatErrors(parsed.error) };\n }\n\n const warnings: string[] = [];\n const data = parsed.data as StudioRecipe;\n for (const field of RESERVED_RECIPE_FIELDS) {\n if (data[field] !== undefined) {\n warnings.push(\n `${field} is reserved for Phase 3 and currently has no effect.`,\n );\n }\n }\n\n return { success: true, data, ...(warnings.length > 0 && { warnings }) };\n}\n","import { parse as yamlParse, stringify as yamlStringify } from \"yaml\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { validateDocument } from \"./validate.js\";\nimport type { ValidationResult } from \"./validate.js\";\n\n/**\n * Parse a YAML string into a validated AtelierDocument.\n * Returns validation errors if the YAML is invalid or doesn't match the schema.\n */\nexport function parseAtelier(yamlString: string): ValidationResult<AtelierDocument> {\n let parsed: unknown;\n try {\n parsed = yamlParse(yamlString);\n } catch (err) {\n return {\n success: false,\n errors: [{ path: \"(yaml)\", message: `YAML parse error: ${(err as Error).message}` }],\n };\n }\n return validateDocument(parsed);\n}\n\n/**\n * Serialize an AtelierDocument to YAML string.\n */\nexport function serializeAtelier(doc: AtelierDocument): string {\n return yamlStringify(doc, { indent: 2 });\n}\n","// @a-company/atelier-mcp — Layer management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Layer, Visual, UnitValue } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\n/** Zod schema for visual objects passed by the AI */\nconst VisualInputSchema = z.object({\n type: z.enum([\"shape\", \"text\", \"image\", \"group\", \"ref\"]).describe(\"Visual type\"),\n // shape visual fields\n shape: z.object({\n type: z.enum([\"rect\", \"ellipse\", \"path\"]),\n cornerRadius: z.union([z.number(), z.tuple([z.number(), z.number(), z.number(), z.number()])]).optional(),\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).optional(),\n closed: z.boolean().optional(),\n }).optional(),\n fill: z.record(z.unknown()).optional(),\n stroke: z.record(z.unknown()).optional(),\n // text visual fields\n content: z.string().optional(),\n style: z.record(z.unknown()).optional(),\n // image visual fields\n assetId: z.string().optional(),\n sourceRect: z.object({\n x: z.number(), y: z.number(), width: z.number().positive(), height: z.number().positive(),\n }).optional(),\n spritesheet: z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n }).optional(),\n frameIndex: z.number().int().min(0).optional(),\n // ref visual fields\n src: z.string().optional(),\n state: z.string().optional(),\n frame: z.number().int().min(0).optional(),\n}).describe(\"Visual content definition\");\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_layer ───────────────────────────────────────\n server.tool(\n \"atelier_add_layer\",\n \"Add a new layer to an Atelier document\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Unique layer ID\"),\n visual: VisualInputSchema.describe(\"Visual content definition\"),\n x: z.union([z.number(), z.string()]).describe(\"X position (pixels or percentage)\"),\n y: z.union([z.number(), z.string()]).describe(\"Y position (pixels or percentage)\"),\n width: z.union([z.number(), z.string()]).describe(\"Width (pixels or percentage)\"),\n height: z.union([z.number(), z.string()]).describe(\"Height (pixels or percentage)\"),\n description: z.string().optional().describe(\"Layer description\"),\n tags: z.array(z.string()).optional().describe(\"Tags\"),\n opacity: z.number().min(0).max(1).optional().describe(\"Opacity 0-1\"),\n rotation: z.number().optional().describe(\"Rotation in degrees\"),\n parentId: z.string().optional().describe(\"Parent layer ID for transform inheritance\"),\n anchorPoint: z.object({ x: z.number(), y: z.number() }).optional().describe(\"Anchor point (0-1 normalized)\"),\n scale: z.object({ x: z.number(), y: z.number() }).optional().describe(\"Scale factors\"),\n visible: z.boolean().optional().describe(\"Whether layer is visible\"),\n tint: z.object({\n color: z.string().describe(\"Tint color (hex string)\"),\n amount: z.number().min(0).max(1).describe(\"Tint amount (0 = none, 1 = full)\"),\n }).optional().describe(\"Color tint overlay\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, visual, x, y, width, height, description, tags, opacity, rotation, parentId, anchorPoint, scale, visible, tint }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n // Check for duplicate layer ID\n if (doc.layers.some(l => l.id === layerId)) {\n return err(`Layer \"${layerId}\" already exists in document \"${id}\"`);\n }\n\n // Validate parentId if provided\n if (parentId && !doc.layers.some(l => l.id === parentId)) {\n return err(`Parent layer \"${parentId}\" not found`);\n }\n\n const layer: Layer = {\n id: layerId,\n visual: visual as unknown as Visual,\n frame: { x: x as UnitValue, y: y as UnitValue },\n bounds: { width: width as UnitValue, height: height as UnitValue },\n ...(description != null ? { description } : {}),\n ...(tags ? { tags } : {}),\n ...(opacity != null ? { opacity } : {}),\n ...(rotation != null ? { rotation } : {}),\n ...(parentId ? { parentId } : {}),\n ...(anchorPoint ? { anchorPoint } : {}),\n ...(scale ? { scale } : {}),\n ...(visible != null ? { visible } : {}),\n ...(tint ? { tint } : {}),\n };\n\n doc.layers.push(layer);\n return ok({ layerId, index: doc.layers.length - 1 });\n },\n );\n\n // ── atelier_edit_layer ──────────────────────────────────────\n server.tool(\n \"atelier_edit_layer\",\n \"Edit properties of an existing layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID to edit\"),\n x: z.union([z.number(), z.string()]).optional().describe(\"New X position\"),\n y: z.union([z.number(), z.string()]).optional().describe(\"New Y position\"),\n width: z.union([z.number(), z.string()]).optional().describe(\"New width\"),\n height: z.union([z.number(), z.string()]).optional().describe(\"New height\"),\n description: z.string().optional().describe(\"New description\"),\n tags: z.array(z.string()).optional().describe(\"New tags\"),\n opacity: z.number().min(0).max(1).optional().describe(\"New opacity\"),\n rotation: z.number().optional().describe(\"New rotation\"),\n parentId: z.string().nullable().optional().describe(\"New parent layer ID (null to clear)\"),\n anchorPoint: z.object({ x: z.number(), y: z.number() }).optional().describe(\"New anchor point\"),\n scale: z.object({ x: z.number(), y: z.number() }).optional().describe(\"New scale\"),\n visible: z.boolean().optional().describe(\"New visibility\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, x, y, width, height, description, tags, opacity, rotation, parentId, anchorPoint, scale, visible }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (x != null) layer.frame.x = x as UnitValue;\n if (y != null) layer.frame.y = y as UnitValue;\n if (width != null) layer.bounds.width = width as UnitValue;\n if (height != null) layer.bounds.height = height as UnitValue;\n if (description != null) layer.description = description;\n if (tags) layer.tags = tags;\n if (opacity != null) layer.opacity = opacity;\n if (rotation != null) layer.rotation = rotation;\n if (parentId !== undefined) {\n if (parentId === null) {\n delete layer.parentId;\n } else {\n if (!doc.layers.some(l => l.id === parentId)) return err(`Parent layer \"${parentId}\" not found`);\n layer.parentId = parentId;\n }\n }\n if (anchorPoint) layer.anchorPoint = anchorPoint;\n if (scale) layer.scale = scale;\n if (visible != null) layer.visible = visible;\n\n return ok({ layerId, updated: true });\n },\n );\n\n // ── atelier_remove_layer ────────────────────────────────────\n server.tool(\n \"atelier_remove_layer\",\n \"Remove a layer from an Atelier document\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, layerId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const index = doc.layers.findIndex(l => l.id === layerId);\n if (index === -1) return err(`Layer \"${layerId}\" not found`);\n\n // Check for deltas that reference this layer\n const warnings: string[] = [];\n for (const [stateName, state] of Object.entries(doc.states)) {\n const deltaCount = state.deltas.filter(d => d.layer === layerId).length;\n if (deltaCount > 0) {\n warnings.push(`State \"${stateName}\" has ${deltaCount} delta(s) referencing this layer`);\n }\n }\n\n // Check for child layers\n const childCount = doc.layers.filter(l => l.parentId === layerId).length;\n if (childCount > 0) {\n warnings.push(`${childCount} child layer(s) reference this layer as parent`);\n }\n\n doc.layers.splice(index, 1);\n return ok({ layerId, removed: true, warnings });\n },\n );\n\n // ── atelier_list_layers ─────────────────────────────────────\n server.tool(\n \"atelier_list_layers\",\n \"List all layers in an Atelier document\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layers = doc.layers.map((l, index) => ({\n index,\n id: l.id,\n type: l.visual.type,\n frame: l.frame,\n bounds: l.bounds,\n description: l.description,\n tags: l.tags,\n opacity: l.opacity,\n rotation: l.rotation,\n parentId: l.parentId,\n visible: l.visible,\n }));\n\n return ok({ layers, count: layers.length });\n },\n );\n\n // ── atelier_reorder ─────────────────────────────────────────\n server.tool(\n \"atelier_reorder\",\n \"Move a layer to a new position in the layer stack\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID to move\"),\n position: z.number().int().min(0).describe(\"Target position index (0-based)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, position }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const currentIndex = doc.layers.findIndex(l => l.id === layerId);\n if (currentIndex === -1) return err(`Layer \"${layerId}\" not found`);\n\n const targetPos = Math.min(position, doc.layers.length - 1);\n const [layer] = doc.layers.splice(currentIndex, 1);\n doc.layers.splice(targetPos, 0, layer);\n\n return ok({ layerId, from: currentIndex, to: targetPos });\n },\n );\n}\n","// @a-company/atelier-mcp — Shape, fill, and stroke tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, ShapeVisual } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_set_shape ───────────────────────────────────────\n server.tool(\n \"atelier_set_shape\",\n \"Set the shape on a shape-type layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID (must be a shape visual)\"),\n shape: z.object({\n type: z.enum([\"rect\", \"ellipse\", \"path\"]).describe(\"Shape type\"),\n cornerRadius: z.union([\n z.number(),\n z.tuple([z.number(), z.number(), z.number(), z.number()]),\n ]).optional().describe(\"Corner radius (rect only)\"),\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).optional().describe(\"Path points (path only)\"),\n closed: z.boolean().optional().describe(\"Whether path is closed (path only)\"),\n }).describe(\"Shape definition\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, shape }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"shape\") return err(`Layer \"${layerId}\" is type \"${layer.visual.type}\", not \"shape\"`);\n\n (layer.visual as ShapeVisual).shape = shape as ShapeVisual[\"shape\"];\n return ok({ layerId, shape: shape.type });\n },\n );\n\n // ── atelier_set_fill ────────────────────────────────────────\n server.tool(\n \"atelier_set_fill\",\n \"Set the fill on a shape-type layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID (must be a shape visual)\"),\n fill: z.object({\n type: z.enum([\"solid\", \"linear-gradient\", \"radial-gradient\"]).describe(\"Fill type\"),\n color: z.unknown().optional().describe(\"Color for solid fill (hex string or RGBA/HSLA object)\"),\n angle: z.number().optional().describe(\"Angle in degrees (linear-gradient only)\"),\n center: z.object({\n x: z.union([z.number(), z.string()]),\n y: z.union([z.number(), z.string()]),\n }).optional().describe(\"Center point (radial-gradient only)\"),\n radius: z.union([z.number(), z.string()]).optional().describe(\"Radius (radial-gradient only)\"),\n stops: z.array(z.object({\n offset: z.number().min(0).max(1),\n color: z.unknown(),\n })).optional().describe(\"Gradient stops\"),\n }).describe(\"Fill definition\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, fill }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"shape\") return err(`Layer \"${layerId}\" is type \"${layer.visual.type}\", not \"shape\"`);\n\n (layer.visual as ShapeVisual).fill = fill as unknown as ShapeVisual[\"fill\"];\n return ok({ layerId, fillType: fill.type });\n },\n );\n\n // ── atelier_set_stroke ──────────────────────────────────────\n server.tool(\n \"atelier_set_stroke\",\n \"Set the stroke on a shape-type layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID (must be a shape visual)\"),\n stroke: z.object({\n color: z.unknown().describe(\"Stroke color (hex string or RGBA/HSLA object)\"),\n width: z.number().positive().describe(\"Stroke width in pixels\"),\n dash: z.array(z.number()).optional().describe(\"Dash pattern\"),\n lineCap: z.enum([\"butt\", \"round\", \"square\"]).optional().describe(\"Line cap style\"),\n lineJoin: z.enum([\"miter\", \"round\", \"bevel\"]).optional().describe(\"Line join style\"),\n }).describe(\"Stroke definition\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, stroke }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"shape\") return err(`Layer \"${layerId}\" is type \"${layer.visual.type}\", not \"shape\"`);\n\n (layer.visual as ShapeVisual).stroke = stroke as unknown as ShapeVisual[\"stroke\"];\n return ok({ layerId, strokeWidth: stroke.width });\n },\n );\n}\n","// @a-company/atelier-mcp — State management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_state ───────────────────────────────────────\n server.tool(\n \"atelier_add_state\",\n \"Add a named animation state to a document\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name (e.g. 'intro', 'hover', 'exit')\"),\n duration: z.number().positive().int().describe(\"Duration in frames\"),\n description: z.string().optional().describe(\"State description\"),\n tags: z.array(z.string()).optional().describe(\"Tags\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, duration, description, tags }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (doc.states[stateName]) {\n return err(`State \"${stateName}\" already exists`);\n }\n\n doc.states[stateName] = {\n duration,\n deltas: [],\n ...(description ? { description } : {}),\n ...(tags ? { tags } : {}),\n };\n\n return ok({ stateName, duration });\n },\n );\n\n // ── atelier_edit_state ──────────────────────────────────────\n server.tool(\n \"atelier_edit_state\",\n \"Edit metadata of an existing animation state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to edit\"),\n duration: z.number().positive().int().optional().describe(\"New duration in frames\"),\n description: z.string().optional().describe(\"New description\"),\n tags: z.array(z.string()).optional().describe(\"New tags\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, duration, description, tags }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (duration != null) state.duration = duration;\n if (description != null) state.description = description;\n if (tags) state.tags = tags;\n\n return ok({ stateName, updated: true });\n },\n );\n\n // ── atelier_remove_state ────────────────────────────────────\n server.tool(\n \"atelier_remove_state\",\n \"Remove an animation state and all its deltas\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, stateName }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) return err(`State \"${stateName}\" not found`);\n\n const deltaCount = doc.states[stateName].deltas.length;\n delete doc.states[stateName];\n\n return ok({ stateName, removed: true, deltasRemoved: deltaCount });\n },\n );\n\n // ── atelier_list_states ─────────────────────────────────────\n server.tool(\n \"atelier_list_states\",\n \"List all animation states in a document\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const states = Object.entries(doc.states).map(([name, state]) => ({\n name,\n duration: state.duration,\n description: state.description,\n tags: state.tags,\n deltaCount: state.deltas.length,\n }));\n\n return ok({ states, count: states.length });\n },\n );\n}\n","// @a-company/atelier-mcp — Delta (animation keyframe) tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Delta, AnimatableProperty, Easing } from \"@a-company/atelier-types\";\nimport { AnimatablePropertySchema, EasingSchema } from \"@a-company/atelier-schema\";\nimport { validateNoOverlap, expandPreset } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\n// Canonical source: @a-company/atelier-schema — single source of truth for AnimatableProperty\nconst AnimatablePropertyEnum = AnimatablePropertySchema;\nconst EasingInputSchema = EasingSchema.describe(\"Easing function\");\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_delta ───────────────────────────────────────\n server.tool(\n \"atelier_add_delta\",\n \"Add an animation delta (keyframe transition) to a state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n layer: z.string().describe(\"Target layer ID\"),\n property: AnimatablePropertyEnum.describe(\"Property to animate\"),\n range: z.tuple([z.number().int().min(0), z.number().int().min(0)]).describe(\"Frame range [start, end] inclusive\"),\n from: z.unknown().describe(\"Starting value\"),\n to: z.unknown().describe(\"Ending value\"),\n easing: EasingInputSchema.optional().describe(\"Easing function\"),\n description: z.string().optional().describe(\"Delta description\"),\n tags: z.array(z.string()).optional().describe(\"Tags\"),\n deltaId: z.string().optional().describe(\"Custom delta ID\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, layer, property, range, from, to, easing, description, tags, deltaId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n // Validate state exists\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n // Validate layer exists\n if (!doc.layers.some(l => l.id === layer)) {\n return err(`Layer \"${layer}\" not found`);\n }\n\n // Validate range\n if (range[0] > range[1]) {\n return err(`Invalid range: start (${range[0]}) must be <= end (${range[1]})`);\n }\n\n const delta: Delta = {\n layer,\n property: property as AnimatableProperty,\n range: [range[0], range[1]],\n from,\n to,\n ...(easing ? { easing: easing as Easing } : {}),\n ...(description ? { description } : {}),\n ...(tags ? { tags } : {}),\n ...(deltaId ? { id: deltaId } : {}),\n };\n\n // Check for overlaps\n const overlap = validateNoOverlap(state.deltas, delta);\n if (overlap) {\n return err(overlap.message);\n }\n\n state.deltas.push(delta);\n return ok({ stateName, deltaIndex: state.deltas.length - 1, layer, property });\n },\n );\n\n // ── atelier_edit_delta ──────────────────────────────────────\n server.tool(\n \"atelier_edit_delta\",\n \"Edit an existing delta by index within a state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n deltaIndex: z.number().int().min(0).describe(\"Delta index within the state\"),\n layer: z.string().optional().describe(\"New target layer ID\"),\n property: AnimatablePropertyEnum.optional().describe(\"New property to animate\"),\n range: z.tuple([z.number().int().min(0), z.number().int().min(0)]).optional().describe(\"New frame range [start, end]\"),\n from: z.unknown().optional().describe(\"New starting value\"),\n to: z.unknown().optional().describe(\"New ending value\"),\n easing: EasingInputSchema.optional().describe(\"New easing function\"),\n description: z.string().optional().describe(\"New description\"),\n tags: z.array(z.string()).optional().describe(\"New tags\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, deltaIndex, layer, property, range, from, to, easing, description, tags }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (deltaIndex >= state.deltas.length) {\n return err(`Delta index ${deltaIndex} out of range (${state.deltas.length} deltas)`);\n }\n\n const delta = state.deltas[deltaIndex];\n\n // Apply updates\n if (layer != null) {\n if (!doc.layers.some(l => l.id === layer)) return err(`Layer \"${layer}\" not found`);\n delta.layer = layer;\n }\n if (property != null) delta.property = property as AnimatableProperty;\n if (range != null) {\n if (range[0] > range[1]) return err(`Invalid range: start (${range[0]}) must be <= end (${range[1]})`);\n delta.range = [range[0], range[1]];\n }\n if (from !== undefined) delta.from = from;\n if (to !== undefined) delta.to = to;\n if (easing != null) delta.easing = easing as Easing;\n if (description != null) delta.description = description;\n if (tags) delta.tags = tags;\n\n // Re-validate overlaps with the updated delta against others\n const others = state.deltas.filter((_, i) => i !== deltaIndex);\n const overlap = validateNoOverlap(others, delta);\n if (overlap) {\n return err(`Edit would cause overlap: ${overlap.message}`);\n }\n\n return ok({ stateName, deltaIndex, updated: true });\n },\n );\n\n // ── atelier_remove_delta ────────────────────────────────────\n server.tool(\n \"atelier_remove_delta\",\n \"Remove a delta by index from a state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n deltaIndex: z.number().int().min(0).describe(\"Delta index to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, stateName, deltaIndex }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (deltaIndex >= state.deltas.length) {\n return err(`Delta index ${deltaIndex} out of range (${state.deltas.length} deltas)`);\n }\n\n const removed = state.deltas.splice(deltaIndex, 1)[0];\n return ok({\n stateName,\n removed: {\n layer: removed.layer,\n property: removed.property,\n range: removed.range,\n },\n remainingDeltas: state.deltas.length,\n });\n },\n );\n\n // ── atelier_apply_preset ────────────────────────────────────\n server.tool(\n \"atelier_apply_preset\",\n \"Apply a preset to a layer, expanding it into concrete deltas\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to add deltas to\"),\n presetName: z.string().describe(\"Preset name defined in the document\"),\n layerId: z.string().describe(\"Target layer ID\"),\n startFrame: z.number().int().min(0).optional().describe(\"Start frame (default: 0)\"),\n duration: z.number().positive().int().optional().describe(\"Duration for preset (default: state duration)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, presetName, layerId, startFrame, duration }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (!doc.layers.some(l => l.id === layerId)) {\n return err(`Layer \"${layerId}\" not found`);\n }\n\n if (!doc.presets || !doc.presets[presetName]) {\n return err(`Preset \"${presetName}\" not found`);\n }\n\n const preset = doc.presets[presetName];\n const start = startFrame ?? 0;\n const dur = duration ?? state.duration;\n\n const deltas = expandPreset(preset, layerId, start, dur);\n\n // Validate no overlaps for each new delta\n const errors: string[] = [];\n for (const delta of deltas) {\n const overlap = validateNoOverlap(state.deltas, delta);\n if (overlap) {\n errors.push(overlap.message);\n }\n }\n\n if (errors.length > 0) {\n return err(`Preset would cause overlaps:\\n${errors.join(\"\\n\")}`);\n }\n\n // Add all deltas\n state.deltas.push(...deltas);\n\n return ok({\n stateName,\n presetName,\n layerId,\n deltasAdded: deltas.length,\n totalDeltas: state.deltas.length,\n });\n },\n );\n}\n","/**\n * Linear easing — no acceleration.\n */\nexport function linear(t: number): number {\n return t;\n}\n\n/**\n * Cubic bezier easing — CSS-compatible.\n * Implements the same algorithm as CSS cubic-bezier().\n * @param x1 - first control point x\n * @param y1 - first control point y\n * @param x2 - second control point x\n * @param y2 - second control point y\n */\nexport function cubicBezier(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n): (t: number) => number {\n // Use binary search to find the parametric t value that gives us our x,\n // then compute the corresponding y. This is the standard algorithm used\n // by browsers for CSS transitions.\n\n return (t: number): number => {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n\n // Binary search for the parametric t value that gives us our x\n let lo = 0;\n let hi = 1;\n let mid: number = 0;\n\n for (let i = 0; i < 20; i++) {\n mid = (lo + hi) / 2;\n const x = sampleBezier(x1, x2, mid);\n if (Math.abs(x - t) < 1e-6) break;\n if (x < t) lo = mid;\n else hi = mid;\n }\n\n mid = (lo + hi) / 2;\n return sampleBezier(y1, y2, mid);\n };\n}\n\n/** Sample a single axis of a cubic bezier at parametric t */\nfunction sampleBezier(p1: number, p2: number, t: number): number {\n // B(t) = 3(1-t)^2*t*p1 + 3(1-t)*t^2*p2 + t^3\n return 3 * (1 - t) * (1 - t) * t * p1 + 3 * (1 - t) * t * t * p2 + t * t * t;\n}\n\n/** Common CSS easing presets */\nexport const easeIn = cubicBezier(0.42, 0, 1, 1);\nexport const easeOut = cubicBezier(0, 0, 0.58, 1);\nexport const easeInOut = cubicBezier(0.42, 0, 0.58, 1);\n\n/**\n * Step easing — jumps between discrete values.\n * @param steps - number of steps\n * @param position - \"start\" or \"end\" (default \"end\")\n */\nexport function step(\n steps: number,\n position: \"start\" | \"end\" = \"end\",\n): (t: number) => number {\n return (t: number): number => {\n if (t <= 0) return position === \"start\" ? 1 / steps : 0;\n if (t >= 1) return 1;\n\n const s = Math.floor(t * steps);\n if (position === \"start\") {\n return Math.min((s + 1) / steps, 1);\n }\n return s / steps;\n };\n}\n","export interface SpringConfig {\n mass?: number; // default 1\n stiffness?: number; // default 100\n damping?: number; // default 10\n velocity?: number; // default 0\n}\n\n/**\n * Creates a spring easing function.\n * Uses damped harmonic oscillator physics.\n * Returns a function that takes t (0-1) and returns the spring value.\n *\n * The spring always goes from 0 to 1, but may overshoot.\n */\nexport function spring(config: SpringConfig = {}): (t: number) => number {\n const {\n mass = 1,\n stiffness = 100,\n damping = 10,\n velocity = 0,\n } = config;\n\n const w0 = Math.sqrt(stiffness / mass); // natural frequency\n const zeta = damping / (2 * Math.sqrt(stiffness * mass)); // damping ratio\n\n // Determine total duration to normalize t\n // We pre-calculate a reasonable duration where the spring settles\n const duration = estimateSettleTime(zeta, w0);\n\n return (t: number): number => {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n\n const time = t * duration;\n let value: number;\n\n if (zeta < 1) {\n // Underdamped\n const wd = w0 * Math.sqrt(1 - zeta * zeta);\n const A = 1;\n const B = (zeta * w0 + velocity) / wd;\n value =\n 1 -\n Math.exp(-zeta * w0 * time) *\n (A * Math.cos(wd * time) + B * Math.sin(wd * time));\n } else if (zeta === 1) {\n // Critically damped\n value = 1 - Math.exp(-w0 * time) * (1 + (w0 + velocity) * time);\n } else {\n // Overdamped\n const s1 = -w0 * (zeta - Math.sqrt(zeta * zeta - 1));\n const s2 = -w0 * (zeta + Math.sqrt(zeta * zeta - 1));\n const A = (velocity - s2) / (s1 - s2);\n const B = 1 - A;\n value = 1 - A * Math.exp(s1 * time) - B * Math.exp(s2 * time);\n }\n\n return value;\n };\n}\n\n/**\n * Estimates the time for a spring to settle within 0.1% of target.\n */\nfunction estimateSettleTime(zeta: number, w0: number): number {\n if (zeta >= 1) {\n return 10 / (zeta * w0);\n }\n // For underdamped: settling ~ -ln(0.001) / (zeta * w0)\n return Math.log(1000) / (zeta * w0);\n}\n","/**\n * Linear interpolation between two numbers.\n */\nexport function lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\n/**\n * Clamp a value between min and max.\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Interpolate between two multi-dimensional values.\n * Arrays must be the same length.\n */\nexport function lerpArray(a: number[], b: number[], t: number): number[] {\n return a.map((v, i) => lerp(v, b[i], t));\n}\n\n/**\n * Re-maps a value from one range to another.\n */\nexport function remap(\n value: number,\n inMin: number,\n inMax: number,\n outMin: number,\n outMax: number,\n): number {\n const t = (value - inMin) / (inMax - inMin);\n return lerp(outMin, outMax, t);\n}\n","import { lerp, clamp } from \"./lerp.js\";\n\nexport interface RGBA {\n r: number; // 0-255\n g: number; // 0-255\n b: number; // 0-255\n a: number; // 0-1\n}\n\nexport interface HSLA {\n h: number; // 0-360\n s: number; // 0-100\n l: number; // 0-100\n a: number; // 0-1\n}\n\n/**\n * Parse a hex color string to RGBA.\n * Supports: #RGB, #RGBA, #RRGGBB, #RRGGBBAA\n */\nexport function hexToRgba(hex: string): RGBA {\n let h = hex.replace(\"#\", \"\");\n\n if (h.length === 3)\n h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2] + \"ff\";\n else if (h.length === 4)\n h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2] + h[3] + h[3];\n else if (h.length === 6) h = h + \"ff\";\n\n return {\n r: parseInt(h.slice(0, 2), 16),\n g: parseInt(h.slice(2, 4), 16),\n b: parseInt(h.slice(4, 6), 16),\n a: parseInt(h.slice(6, 8), 16) / 255,\n };\n}\n\n/**\n * Convert RGBA to hex string.\n */\nexport function rgbaToHex(color: RGBA): string {\n const r = clamp(Math.round(color.r), 0, 255)\n .toString(16)\n .padStart(2, \"0\");\n const g = clamp(Math.round(color.g), 0, 255)\n .toString(16)\n .padStart(2, \"0\");\n const b = clamp(Math.round(color.b), 0, 255)\n .toString(16)\n .padStart(2, \"0\");\n const a = clamp(Math.round(color.a * 255), 0, 255)\n .toString(16)\n .padStart(2, \"0\");\n return `#${r}${g}${b}${a === \"ff\" ? \"\" : a}`;\n}\n\n/**\n * Interpolate between two RGBA colors.\n */\nexport function lerpRgba(a: RGBA, b: RGBA, t: number): RGBA {\n return {\n r: lerp(a.r, b.r, t),\n g: lerp(a.g, b.g, t),\n b: lerp(a.b, b.b, t),\n a: lerp(a.a, b.a, t),\n };\n}\n\n/**\n * Convert RGBA to HSLA.\n */\nexport function rgbaToHsla(color: RGBA): HSLA {\n const r = color.r / 255;\n const g = color.g / 255;\n const b = color.b / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const d = max - min;\n const l = (max + min) / 2;\n\n let h = 0;\n let s = 0;\n\n if (d !== 0) {\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n else if (max === g) h = ((b - r) / d + 2) / 6;\n else h = ((r - g) / d + 4) / 6;\n }\n\n return { h: h * 360, s: s * 100, l: l * 100, a: color.a };\n}\n\n/**\n * Convert HSLA to RGBA.\n */\nexport function hslaToRgba(color: HSLA): RGBA {\n const h = color.h / 360;\n const s = color.s / 100;\n const l = color.l / 100;\n\n let r: number, g: number, b: number;\n\n if (s === 0) {\n r = g = b = l;\n } else {\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n r = hueToRgb(p, q, h + 1 / 3);\n g = hueToRgb(p, q, h);\n b = hueToRgb(p, q, h - 1 / 3);\n }\n\n return {\n r: Math.round(r * 255),\n g: Math.round(g * 255),\n b: Math.round(b * 255),\n a: color.a,\n };\n}\n\nfunction hueToRgb(p: number, q: number, t: number): number {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n}\n\n/**\n * Interpolate between two HSLA colors (shortest hue path).\n */\nexport function lerpHsla(a: HSLA, b: HSLA, t: number): HSLA {\n // Handle hue wrapping — take the shortest path\n let dh = b.h - a.h;\n if (dh > 180) dh -= 360;\n if (dh < -180) dh += 360;\n\n return {\n h: (((a.h + dh * t) % 360) + 360) % 360,\n s: lerp(a.s, b.s, t),\n l: lerp(a.l, b.l, t),\n a: lerp(a.a, b.a, t),\n };\n}\n","/**\n * Path interpolation utilities for motion paths.\n * Evaluates position and tangent along a path defined by points with bezier handles.\n */\n\nexport interface PathPoint2D {\n x: number;\n y: number;\n in?: { x: number; y: number };\n out?: { x: number; y: number };\n}\n\nexport interface PathPosition {\n x: number;\n y: number;\n /** Tangent angle in degrees */\n angle: number;\n}\n\n/**\n * Compute the length of a single cubic bezier segment using subdivision.\n */\nfunction bezierSegmentLength(\n p0x: number, p0y: number,\n c0x: number, c0y: number,\n c1x: number, c1y: number,\n p1x: number, p1y: number,\n steps = 32,\n): number {\n let length = 0;\n let prevX = p0x;\n let prevY = p0y;\n for (let i = 1; i <= steps; i++) {\n const t = i / steps;\n const mt = 1 - t;\n const x = mt * mt * mt * p0x + 3 * mt * mt * t * c0x + 3 * mt * t * t * c1x + t * t * t * p1x;\n const y = mt * mt * mt * p0y + 3 * mt * mt * t * c0y + 3 * mt * t * t * c1y + t * t * t * p1y;\n const dx = x - prevX;\n const dy = y - prevY;\n length += Math.sqrt(dx * dx + dy * dy);\n prevX = x;\n prevY = y;\n }\n return length;\n}\n\n/**\n * Evaluate a cubic bezier at parameter t, returning position and tangent.\n */\nfunction evalBezier(\n p0x: number, p0y: number,\n c0x: number, c0y: number,\n c1x: number, c1y: number,\n p1x: number, p1y: number,\n t: number,\n): PathPosition {\n const mt = 1 - t;\n const x = mt * mt * mt * p0x + 3 * mt * mt * t * c0x + 3 * mt * t * t * c1x + t * t * t * p1x;\n const y = mt * mt * mt * p0y + 3 * mt * mt * t * c0y + 3 * mt * t * t * c1y + t * t * t * p1y;\n\n // Tangent (first derivative)\n const tx = 3 * mt * mt * (c0x - p0x) + 6 * mt * t * (c1x - c0x) + 3 * t * t * (p1x - c1x);\n const ty = 3 * mt * mt * (c0y - p0y) + 6 * mt * t * (c1y - c0y) + 3 * t * t * (p1y - c1y);\n\n const angle = Math.atan2(ty, tx) * (180 / Math.PI);\n\n return { x, y, angle };\n}\n\n/**\n * Build a lookup table of cumulative segment lengths for a path.\n */\nfunction buildSegmentLengths(points: PathPoint2D[], closed: boolean): number[] {\n const segCount = closed ? points.length : points.length - 1;\n const lengths: number[] = [];\n\n for (let i = 0; i < segCount; i++) {\n const p0 = points[i];\n const p1 = points[(i + 1) % points.length];\n\n const c0x = p0.x + (p0.out?.x ?? 0);\n const c0y = p0.y + (p0.out?.y ?? 0);\n const c1x = p1.x + (p1.in?.x ?? 0);\n const c1y = p1.y + (p1.in?.y ?? 0);\n\n lengths.push(bezierSegmentLength(p0.x, p0.y, c0x, c0y, c1x, c1y, p1.x, p1.y));\n }\n\n return lengths;\n}\n\n/**\n * Evaluate a point along a path at a given progress (0–1).\n * Uses arc-length parameterization for uniform speed.\n */\nexport function evaluatePathAtProgress(\n points: PathPoint2D[],\n progress: number,\n closed = false,\n): PathPosition {\n if (points.length < 2) {\n return { x: points[0]?.x ?? 0, y: points[0]?.y ?? 0, angle: 0 };\n }\n\n // Clamp progress\n const t = Math.max(0, Math.min(1, progress));\n\n const segLengths = buildSegmentLengths(points, closed);\n const totalLength = segLengths.reduce((a, b) => a + b, 0);\n\n if (totalLength === 0) {\n return { x: points[0].x, y: points[0].y, angle: 0 };\n }\n\n const targetLength = t * totalLength;\n\n // Find which segment the target length falls in\n let accumulated = 0;\n for (let i = 0; i < segLengths.length; i++) {\n const segLen = segLengths[i];\n if (accumulated + segLen >= targetLength || i === segLengths.length - 1) {\n // Progress within this segment\n const segProgress = segLen === 0 ? 0 : (targetLength - accumulated) / segLen;\n\n const p0 = points[i];\n const p1 = points[(i + 1) % points.length];\n\n const c0x = p0.x + (p0.out?.x ?? 0);\n const c0y = p0.y + (p0.out?.y ?? 0);\n const c1x = p1.x + (p1.in?.x ?? 0);\n const c1y = p1.y + (p1.in?.y ?? 0);\n\n return evalBezier(p0.x, p0.y, c0x, c0y, c1x, c1y, p1.x, p1.y, segProgress);\n }\n accumulated += segLen;\n }\n\n // Fallback (shouldn't reach here)\n const last = points[points.length - 1];\n return { x: last.x, y: last.y, angle: 0 };\n}\n","import type { Delta, FrameRange } from \"@a-company/atelier-types\";\nimport { lerp, clamp, hexToRgba, lerpRgba, rgbaToHex } from \"@a-company/atelier-math\";\nimport { resolveEasing } from \"./easing-resolver.js\";\nimport { isExpression, evaluateExpression, type ExpressionContext } from \"../expressions/expression-evaluator.js\";\n\n/**\n * Check if a frame is within a delta's range (inclusive).\n */\nexport function isFrameInRange(frame: number, range: FrameRange): boolean {\n return frame >= range[0] && frame <= range[1];\n}\n\n/**\n * Compute the progress (0-1) of a frame within a delta's range.\n */\nexport function computeProgress(frame: number, range: FrameRange): number {\n const [start, end] = range;\n if (start === end) return 1; // instantaneous\n return clamp((frame - start) / (end - start), 0, 1);\n}\n\n/**\n * Resolve a single delta's value at a given frame.\n * Returns undefined if the frame is outside the delta's range.\n * Returns the interpolated value if within range.\n *\n * If `from` or `to` is an expression object `{ expr: \"...\" }`,\n * it is evaluated with the current animation context before interpolation.\n */\nexport function resolveDeltaValue(delta: Delta, frame: number): unknown | undefined {\n if (!isFrameInRange(frame, delta.range)) {\n return undefined;\n }\n\n const progress = computeProgress(frame, delta.range);\n const easingFn = resolveEasing(delta.easing);\n const easedProgress = easingFn(progress);\n\n const exprCtx: ExpressionContext = {\n t: easedProgress,\n progress,\n frame,\n duration: delta.range[1] - delta.range[0],\n };\n\n const from = isExpression(delta.from)\n ? evaluateExpression(delta.from.expr, exprCtx)\n : delta.from;\n\n const to = isExpression(delta.to)\n ? evaluateExpression(delta.to.expr, exprCtx)\n : delta.to;\n\n return interpolateValue(from, to, easedProgress);\n}\n\n/**\n * Interpolate between two values based on eased progress.\n * Handles numbers, strings (pass-through at threshold), and nested objects.\n */\nexport function interpolateValue(from: unknown, to: unknown, t: number): unknown {\n // Number interpolation\n if (typeof from === \"number\" && typeof to === \"number\") {\n return lerp(from, to, t);\n }\n\n // Hex color interpolation\n if (typeof from === \"string\" && typeof to === \"string\") {\n if (from.startsWith(\"#\") && to.startsWith(\"#\")) {\n return rgbaToHex(lerpRgba(hexToRgba(from), hexToRgba(to), t));\n }\n // Non-color strings — snap at end\n return t >= 1 ? to : from;\n }\n\n // Boolean interpolation — snap at midpoint for frame-precise control\n if (typeof from === \"boolean\" && typeof to === \"boolean\") {\n return t >= 0.5 ? to : from;\n }\n\n // For unknown types, snap at end\n return t >= 1 ? to : from;\n}\n\n/**\n * Given multiple deltas for the SAME layer+property, find the active one\n * at a given frame and return its resolved value.\n *\n * If no delta is active at this frame, holds the `to` value of the most\n * recent completed delta (the one whose range ended most recently before\n * this frame). This prevents properties from reverting after animation ends.\n *\n * Assumes no overlaps (validated elsewhere).\n */\nexport function resolvePropertyAtFrame(\n deltas: Delta[],\n frame: number,\n): unknown | undefined {\n // Check for an active delta first\n for (const delta of deltas) {\n if (isFrameInRange(frame, delta.range)) {\n return resolveDeltaValue(delta, frame);\n }\n }\n\n // No active delta — hold the `to` value of the most recently completed delta\n let lastCompleted: Delta | undefined;\n for (const delta of deltas) {\n if (frame > delta.range[1]) {\n if (!lastCompleted || delta.range[1] > lastCompleted.range[1]) {\n lastCompleted = delta;\n }\n }\n }\n\n if (!lastCompleted) return undefined;\n\n // If the held `to` value is an expression, evaluate at t=1\n if (isExpression(lastCompleted.to)) {\n return evaluateExpression(lastCompleted.to.expr, {\n t: 1,\n progress: 1,\n frame,\n duration: lastCompleted.range[1] - lastCompleted.range[0],\n });\n }\n\n return lastCompleted.to;\n}\n","import type { Easing } from \"@a-company/atelier-types\";\nimport { linear, cubicBezier, easeIn, easeOut, easeInOut, step, spring } from \"@a-company/atelier-math\";\n\n/**\n * Converts an Easing type definition into an executable easing function.\n * Returns a function (t: number) => number where t is 0-1.\n */\nexport function resolveEasing(easing: Easing | undefined): (t: number) => number {\n if (!easing) return linear;\n\n // String presets\n if (typeof easing === \"string\") {\n switch (easing) {\n case \"linear\": return linear;\n case \"ease-in\": return easeIn;\n case \"ease-out\": return easeOut;\n case \"ease-in-out\": return easeInOut;\n default: return linear;\n }\n }\n\n // Object easing definitions\n switch (easing.type) {\n case \"linear\":\n return linear;\n case \"cubic-bezier\":\n return cubicBezier(easing.x1, easing.y1, easing.x2, easing.y2);\n case \"spring\":\n return spring({\n mass: easing.mass,\n stiffness: easing.stiffness,\n damping: easing.damping,\n velocity: easing.velocity,\n });\n case \"step\":\n return step(easing.steps, easing.position);\n default:\n return linear;\n }\n}\n","/**\n * Safe recursive descent expression evaluator.\n * No eval(), no Function(), no code generation.\n *\n * Supports:\n * - Numbers: 42, 3.14, -1\n * - Operators: + - * / % **\n * - Parentheses: (expr)\n * - Math functions: sin, cos, tan, abs, min, max, floor, ceil, round, sqrt, pow, clamp, sign, log\n * - Constants: pi, tau, e\n * - Context variables: t, frame, duration, progress\n * - Comparison: <, >, <=, >=, ==, !=\n * - Ternary: condition ? trueExpr : falseExpr\n */\n\n/** Context variables available during expression evaluation */\nexport interface ExpressionContext {\n /** Eased progress 0–1 */\n t: number;\n /** Raw progress 0–1 (before easing) */\n progress: number;\n /** Current frame number */\n frame: number;\n /** Delta duration in frames */\n duration: number;\n}\n\n// ── Tokenizer ───────────────────────────────────────────────\n\ntype TokenType =\n | \"number\"\n | \"ident\"\n | \"op\"\n | \"lparen\"\n | \"rparen\"\n | \"comma\"\n | \"question\"\n | \"colon\"\n | \"compare\"\n | \"eof\";\n\ninterface Token {\n type: TokenType;\n value: string;\n}\n\nfunction tokenize(expr: string): Token[] {\n const tokens: Token[] = [];\n let i = 0;\n\n while (i < expr.length) {\n const ch = expr[i];\n\n // Whitespace\n if (ch === \" \" || ch === \"\\t\" || ch === \"\\n\" || ch === \"\\r\") {\n i++;\n continue;\n }\n\n // Numbers\n if ((ch >= \"0\" && ch <= \"9\") || ch === \".\") {\n let num = \"\";\n while (i < expr.length && ((expr[i] >= \"0\" && expr[i] <= \"9\") || expr[i] === \".\")) {\n num += expr[i++];\n }\n tokens.push({ type: \"number\", value: num });\n continue;\n }\n\n // Identifiers (variables, functions, constants)\n if ((ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\") || ch === \"_\") {\n let id = \"\";\n while (i < expr.length && ((expr[i] >= \"a\" && expr[i] <= \"z\") || (expr[i] >= \"A\" && expr[i] <= \"Z\") || (expr[i] >= \"0\" && expr[i] <= \"9\") || expr[i] === \"_\")) {\n id += expr[i++];\n }\n tokens.push({ type: \"ident\", value: id });\n continue;\n }\n\n // Comparison operators (must check before single-char ops)\n if (ch === \"<\" || ch === \">\" || ch === \"!\" || ch === \"=\") {\n if (i + 1 < expr.length && expr[i + 1] === \"=\") {\n tokens.push({ type: \"compare\", value: ch + \"=\" });\n i += 2;\n continue;\n }\n if (ch === \"<\" || ch === \">\") {\n tokens.push({ type: \"compare\", value: ch });\n i++;\n continue;\n }\n }\n\n // Power operator\n if (ch === \"*\" && i + 1 < expr.length && expr[i + 1] === \"*\") {\n tokens.push({ type: \"op\", value: \"**\" });\n i += 2;\n continue;\n }\n\n // Operators\n if (ch === \"+\" || ch === \"-\" || ch === \"*\" || ch === \"/\" || ch === \"%\") {\n tokens.push({ type: \"op\", value: ch });\n i++;\n continue;\n }\n\n // Grouping and function calls\n if (ch === \"(\") { tokens.push({ type: \"lparen\", value: \"(\" }); i++; continue; }\n if (ch === \")\") { tokens.push({ type: \"rparen\", value: \")\" }); i++; continue; }\n if (ch === \",\") { tokens.push({ type: \"comma\", value: \",\" }); i++; continue; }\n\n // Ternary\n if (ch === \"?\") { tokens.push({ type: \"question\", value: \"?\" }); i++; continue; }\n if (ch === \":\") { tokens.push({ type: \"colon\", value: \":\" }); i++; continue; }\n\n throw new Error(`Expression: unexpected character '${ch}' at position ${i}`);\n }\n\n tokens.push({ type: \"eof\", value: \"\" });\n return tokens;\n}\n\n// ── Parser + Evaluator ──────────────────────────────────────\n\nconst CONSTANTS: Record<string, number> = {\n pi: Math.PI,\n PI: Math.PI,\n tau: Math.PI * 2,\n TAU: Math.PI * 2,\n e: Math.E,\n E: Math.E,\n};\n\nconst FUNCTIONS: Record<string, (...args: number[]) => number> = {\n sin: Math.sin,\n cos: Math.cos,\n tan: Math.tan,\n abs: Math.abs,\n floor: Math.floor,\n ceil: Math.ceil,\n round: Math.round,\n sqrt: Math.sqrt,\n sign: Math.sign,\n log: Math.log,\n min: (...args) => Math.min(...args),\n max: (...args) => Math.max(...args),\n pow: (a, b) => Math.pow(a, b),\n clamp: (v, lo, hi) => Math.min(Math.max(v, lo), hi),\n};\n\nclass Parser {\n private tokens: Token[];\n private pos = 0;\n private ctx: ExpressionContext;\n\n constructor(tokens: Token[], ctx: ExpressionContext) {\n this.tokens = tokens;\n this.ctx = ctx;\n }\n\n private peek(): Token {\n return this.tokens[this.pos];\n }\n\n private consume(expectedType?: TokenType): Token {\n const tok = this.tokens[this.pos++];\n if (expectedType && tok.type !== expectedType) {\n throw new Error(`Expression: expected ${expectedType} but got ${tok.type} '${tok.value}'`);\n }\n return tok;\n }\n\n /** Entry: ternary (lowest precedence) */\n parse(): number {\n const result = this.parseTernary();\n if (this.peek().type !== \"eof\") {\n throw new Error(`Expression: unexpected token '${this.peek().value}'`);\n }\n return result;\n }\n\n /** ternary: comparison ? expr : expr */\n private parseTernary(): number {\n const condition = this.parseComparison();\n if (this.peek().type === \"question\") {\n this.consume(); // ?\n const trueVal = this.parseTernary();\n this.consume(\"colon\"); // :\n const falseVal = this.parseTernary();\n return condition ? trueVal : falseVal;\n }\n return condition;\n }\n\n /** comparison: additive (< | > | <= | >= | == | !=) additive */\n private parseComparison(): number {\n let left = this.parseAdditive();\n while (this.peek().type === \"compare\") {\n const op = this.consume().value;\n const right = this.parseAdditive();\n switch (op) {\n case \"<\": left = left < right ? 1 : 0; break;\n case \">\": left = left > right ? 1 : 0; break;\n case \"<=\": left = left <= right ? 1 : 0; break;\n case \">=\": left = left >= right ? 1 : 0; break;\n case \"==\": left = left === right ? 1 : 0; break;\n case \"!=\": left = left !== right ? 1 : 0; break;\n }\n }\n return left;\n }\n\n /** additive: multiplicative (('+' | '-') multiplicative)* */\n private parseAdditive(): number {\n let left = this.parseMultiplicative();\n while (this.peek().type === \"op\" && (this.peek().value === \"+\" || this.peek().value === \"-\")) {\n const op = this.consume().value;\n const right = this.parseMultiplicative();\n left = op === \"+\" ? left + right : left - right;\n }\n return left;\n }\n\n /** multiplicative: power (('*' | '/' | '%') power)* */\n private parseMultiplicative(): number {\n let left = this.parsePower();\n while (this.peek().type === \"op\" && (this.peek().value === \"*\" || this.peek().value === \"/\" || this.peek().value === \"%\")) {\n const op = this.consume().value;\n const right = this.parsePower();\n if (op === \"*\") left = left * right;\n else if (op === \"/\") left = right !== 0 ? left / right : 0;\n else left = left % right;\n }\n return left;\n }\n\n /** power: unary ('**' unary)* (right-associative) */\n private parsePower(): number {\n const base = this.parseUnary();\n if (this.peek().type === \"op\" && this.peek().value === \"**\") {\n this.consume();\n const exp = this.parsePower(); // right-associative\n return Math.pow(base, exp);\n }\n return base;\n }\n\n /** unary: ('-' | '+') unary | primary */\n private parseUnary(): number {\n if (this.peek().type === \"op\" && (this.peek().value === \"-\" || this.peek().value === \"+\")) {\n const op = this.consume().value;\n const val = this.parseUnary();\n return op === \"-\" ? -val : val;\n }\n return this.parsePrimary();\n }\n\n /** primary: number | ident | function(args) | '(' expr ')' */\n private parsePrimary(): number {\n const tok = this.peek();\n\n // Number literal\n if (tok.type === \"number\") {\n this.consume();\n return parseFloat(tok.value);\n }\n\n // Identifier: constant, context variable, or function\n if (tok.type === \"ident\") {\n this.consume();\n const name = tok.value;\n\n // Function call\n if (this.peek().type === \"lparen\") {\n this.consume(); // (\n const args: number[] = [];\n if (this.peek().type !== \"rparen\") {\n args.push(this.parseTernary());\n while (this.peek().type === \"comma\") {\n this.consume(); // ,\n args.push(this.parseTernary());\n }\n }\n this.consume(\"rparen\"); // )\n\n const fn = FUNCTIONS[name];\n if (!fn) throw new Error(`Expression: unknown function '${name}'`);\n return fn(...args);\n }\n\n // Constant\n if (name in CONSTANTS) return CONSTANTS[name];\n\n // Context variable\n if (name in this.ctx) return (this.ctx as unknown as Record<string, number>)[name];\n\n throw new Error(`Expression: unknown variable '${name}'`);\n }\n\n // Parenthesized expression\n if (tok.type === \"lparen\") {\n this.consume(); // (\n const val = this.parseTernary();\n this.consume(\"rparen\"); // )\n return val;\n }\n\n throw new Error(`Expression: unexpected token '${tok.value}'`);\n }\n}\n\n// ── Public API ──────────────────────────────────────────────\n\n/**\n * Check if a value is an expression object { expr: string }.\n */\nexport function isExpression(value: unknown): value is { expr: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"expr\" in value &&\n typeof (value as Record<string, unknown>).expr === \"string\"\n );\n}\n\n/**\n * Evaluate an expression string with the given context.\n * Returns a number. Throws on syntax errors or unknown identifiers.\n */\nexport function evaluateExpression(expr: string, ctx: ExpressionContext): number {\n const tokens = tokenize(expr);\n const parser = new Parser(tokens, ctx);\n return parser.parse();\n}\n","import type { AtelierDocument, Layer, Delta, AnimatableProperty } from \"@a-company/atelier-types\";\nimport { resolvePropertyAtFrame } from \"./delta-resolver.js\";\n\n/** A resolved layer at a specific frame — all animated properties computed */\nexport interface ResolvedLayer {\n id: string;\n /** Original layer definition */\n layer: Layer;\n /** Computed property overrides from active deltas */\n computedProperties: Partial<Record<AnimatableProperty, unknown>>;\n /** Seconds into source video to seek to — only present for video visual layers */\n videoSourceTime?: number;\n}\n\n/** The resolved state of an entire document at a specific frame */\nexport interface ResolvedFrame {\n /** Frame number that was resolved */\n frame: number;\n /** State name that was resolved */\n stateName: string;\n /** All layers with their computed properties */\n layers: ResolvedLayer[];\n}\n\n/**\n * Resolve all layers at a given frame within a named state.\n * This is the main entry point for frame resolution.\n * @param overrideDeltas - Optional pre-merged deltas (used for hierarchical state resolution)\n */\nexport function resolveFrame(\n doc: AtelierDocument,\n stateName: string,\n frame: number,\n overrideDeltas?: Delta[],\n): ResolvedFrame {\n const state = doc.states[stateName];\n if (!state) {\n throw new Error(`State \"${stateName}\" not found in document \"${doc.name}\"`);\n }\n\n // Group deltas by layer+property\n const deltasByLayerProperty = groupDeltas(overrideDeltas ?? state.deltas);\n\n // Resolve each layer\n const resolvedLayers: ResolvedLayer[] = doc.layers.map((layer) => {\n const computedProperties: Partial<Record<AnimatableProperty, unknown>> = {};\n\n // Find all animated properties for this layer\n const layerDeltas = deltasByLayerProperty.get(layer.id);\n if (layerDeltas) {\n for (const [property, deltas] of layerDeltas) {\n const value = resolvePropertyAtFrame(deltas, frame);\n if (value !== undefined) {\n computedProperties[property as AnimatableProperty] = value;\n }\n }\n }\n\n const resolvedLayer: ResolvedLayer = { id: layer.id, layer, computedProperties };\n\n if (layer.visual.type === \"video\") {\n const video = layer.visual;\n const fps = doc.canvas.fps;\n const startFrame = video.startFrame ?? 0;\n const sourceOffset = video.sourceOffset ?? 0;\n const playbackRate = video.playbackRate ?? 1.0;\n const relativeFrame = Math.max(0, frame - startFrame);\n const sourceTime = (relativeFrame / fps) * playbackRate + sourceOffset;\n resolvedLayer.videoSourceTime =\n video.sourceEnd !== undefined ? Math.min(sourceTime, video.sourceEnd) : sourceTime;\n }\n\n return resolvedLayer;\n });\n\n return { frame, stateName, layers: resolvedLayers };\n}\n\n/**\n * Group deltas by layer ID, then by property name.\n */\nfunction groupDeltas(\n deltas: Delta[],\n): Map<string, Map<string, Delta[]>> {\n const map = new Map<string, Map<string, Delta[]>>();\n\n for (const delta of deltas) {\n let layerMap = map.get(delta.layer);\n if (!layerMap) {\n layerMap = new Map();\n map.set(delta.layer, layerMap);\n }\n\n let propDeltas = layerMap.get(delta.property);\n if (!propDeltas) {\n propDeltas = [];\n layerMap.set(delta.property, propDeltas);\n }\n\n propDeltas.push(delta);\n }\n\n return map;\n}\n","import type { Delta, FrameRange } from \"@a-company/atelier-types\";\n\nexport interface OverlapError {\n layerId: string;\n property: string;\n existingRange: FrameRange;\n newRange: FrameRange;\n message: string;\n}\n\n/**\n * Check if two frame ranges overlap.\n * Boundary-touching ranges (e.g., [0-50] and [50-90]) are allowed —\n * only ranges that share more than a single boundary frame are overlaps.\n */\nexport function rangesOverlap(a: FrameRange, b: FrameRange): boolean {\n return a[0] < b[1] && b[0] < a[1];\n}\n\n/**\n * Validate that a new delta doesn't overlap with existing deltas\n * on the same layer+property.\n */\nexport function validateNoOverlap(\n existing: Delta[],\n newDelta: Delta,\n): OverlapError | null {\n for (const delta of existing) {\n if (\n delta.layer === newDelta.layer &&\n delta.property === newDelta.property &&\n rangesOverlap(delta.range, newDelta.range)\n ) {\n return {\n layerId: newDelta.layer,\n property: newDelta.property,\n existingRange: delta.range,\n newRange: newDelta.range,\n message: `Overlapping delta on layer \"${newDelta.layer}\" property \"${newDelta.property}\": ` +\n `existing [${delta.range[0]}-${delta.range[1]}] overlaps with new [${newDelta.range[0]}-${newDelta.range[1]}]`,\n };\n }\n }\n return null;\n}\n\n/**\n * Validate all deltas in a state have no overlaps.\n * Returns all overlap errors found.\n */\nexport function validateAllDeltas(deltas: Delta[]): OverlapError[] {\n const errors: OverlapError[] = [];\n\n for (let i = 0; i < deltas.length; i++) {\n for (let j = i + 1; j < deltas.length; j++) {\n const a = deltas[i];\n const b = deltas[j];\n\n if (\n a.layer === b.layer &&\n a.property === b.property &&\n rangesOverlap(a.range, b.range)\n ) {\n errors.push({\n layerId: a.layer,\n property: a.property,\n existingRange: a.range,\n newRange: b.range,\n message: `Overlapping deltas on layer \"${a.layer}\" property \"${a.property}\": ` +\n `[${a.range[0]}-${a.range[1]}] overlaps with [${b.range[0]}-${b.range[1]}]`,\n });\n }\n }\n }\n\n return errors;\n}\n","import type {\n AtelierDocument, Canvas, Layer, State, Delta, Preset,\n Variable, Asset,\n} from \"@a-company/atelier-types\";\nimport { validateNoOverlap } from \"../validation/overlap-validator.js\";\n\n/**\n * Fluent builder for constructing AtelierDocument objects.\n * Validates constraints (like no-overlap) as you build.\n */\nexport class DocumentBuilder {\n private doc: AtelierDocument;\n\n constructor(name: string, canvas: Canvas) {\n this.doc = {\n version: \"1.0\",\n name,\n canvas,\n layers: [],\n states: {},\n };\n }\n\n /** Set document description */\n description(desc: string): this {\n this.doc.description = desc;\n return this;\n }\n\n /** Add tags to the document */\n tags(...tags: string[]): this {\n this.doc.tags = [...(this.doc.tags ?? []), ...tags];\n return this;\n }\n\n /** Add a variable definition */\n variable(id: string, variable: Variable): this {\n if (!this.doc.variables) this.doc.variables = {};\n this.doc.variables[id] = variable;\n return this;\n }\n\n /** Add an asset reference */\n asset(id: string, asset: Asset): this {\n if (!this.doc.assets) this.doc.assets = {};\n this.doc.assets[id] = asset;\n return this;\n }\n\n /** Add a preset */\n preset(id: string, preset: Preset): this {\n if (!this.doc.presets) this.doc.presets = {};\n this.doc.presets[id] = preset;\n return this;\n }\n\n /** Add a layer */\n addLayer(layer: Layer): this {\n // Check for duplicate IDs\n if (this.doc.layers.some(l => l.id === layer.id)) {\n throw new Error(`Layer with id \"${layer.id}\" already exists`);\n }\n this.doc.layers.push(layer);\n return this;\n }\n\n /** Add a state */\n addState(name: string, state: Omit<State, \"deltas\"> & { deltas?: Delta[] }): this {\n if (this.doc.states[name]) {\n throw new Error(`State \"${name}\" already exists`);\n }\n this.doc.states[name] = { ...state, deltas: state.deltas ?? [] };\n return this;\n }\n\n /** Add a delta to an existing state, with overlap validation */\n addDelta(stateName: string, delta: Delta): this {\n const state = this.doc.states[stateName];\n if (!state) {\n throw new Error(`State \"${stateName}\" not found`);\n }\n\n // Verify the layer exists\n if (!this.doc.layers.some(l => l.id === delta.layer)) {\n throw new Error(`Layer \"${delta.layer}\" not found — add the layer before adding deltas`);\n }\n\n // Check for overlaps\n const overlap = validateNoOverlap(state.deltas, delta);\n if (overlap) {\n throw new Error(overlap.message);\n }\n\n state.deltas.push(delta);\n return this;\n }\n\n /** Build and return the final document */\n build(): AtelierDocument {\n return JSON.parse(JSON.stringify(this.doc)) as AtelierDocument;\n }\n}\n\n/**\n * Create a new DocumentBuilder.\n * Convenience function for starting a builder chain.\n */\nexport function createDocument(name: string, canvas: Canvas): DocumentBuilder {\n return new DocumentBuilder(name, canvas);\n}\n","import type { UnitValue } from \"@a-company/atelier-types\";\n\n/**\n * Check if a UnitValue is a percentage string.\n */\nexport function isPercentage(value: UnitValue): value is `${number}%` {\n return typeof value === \"string\" && value.endsWith(\"%\");\n}\n\n/**\n * Parse a percentage string to its numeric value (0-100).\n */\nexport function parsePercentage(value: `${number}%`): number {\n return parseFloat(value);\n}\n\n/**\n * Resolve a UnitValue to pixels given a reference dimension.\n * Pixel values pass through unchanged.\n * Percentage values are computed relative to the reference.\n */\nexport function resolveUnit(value: UnitValue, reference: number): number {\n if (isPercentage(value)) {\n return (parsePercentage(value) / 100) * reference;\n }\n return value;\n}\n","import type { Preset, Delta, FrameRange } from \"@a-company/atelier-types\";\n\n/**\n * Expand a preset into concrete deltas for a specific layer and start frame.\n *\n * @param preset - The preset to expand\n * @param layerId - Target layer ID\n * @param startFrame - Frame to start the preset from\n * @param duration - Total duration to map preset offsets into\n */\nexport function expandPreset(\n preset: Preset,\n layerId: string,\n startFrame: number,\n duration: number,\n): Delta[] {\n return preset.deltas.map((pd, index) => {\n let range: FrameRange;\n if (pd.offset) {\n range = [startFrame + pd.offset[0], startFrame + pd.offset[1]];\n } else {\n range = [startFrame, startFrame + duration];\n }\n\n return {\n id: `preset-${layerId}-${index}`,\n layer: layerId,\n property: pd.property,\n range,\n from: pd.from,\n to: pd.to,\n easing: pd.easing,\n };\n });\n}\n","import type { AtelierDocument, Easing, State, Delta } from \"@a-company/atelier-types\";\nimport { resolveFrame, type ResolvedFrame } from \"../resolver/frame-resolver.js\";\nimport { resolveEasing } from \"../resolver/easing-resolver.js\";\n\nexport interface StateTransition {\n from: string;\n to: string;\n at: number; // frame at which transition occurs\n}\n\nexport interface PlaybackState {\n stateName: string;\n frame: number;\n resolved: ResolvedFrame;\n isComplete: boolean;\n}\n\nexport interface ActiveTransition {\n fromState: string;\n toState: string;\n duration: number;\n easingFn: (t: number) => number;\n transitionFrame: number; // how many frames into the transition\n}\n\nexport class StateMachine {\n private currentState: string;\n private currentFrame = 0;\n private transitions: StateTransition[] = [];\n private activeTransition: ActiveTransition | null = null;\n\n constructor(\n private doc: AtelierDocument,\n initialState?: string,\n ) {\n // Default to first state\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) throw new Error(\"Document has no states\");\n this.currentState = initialState ?? stateNames[0];\n if (!doc.states[this.currentState]) {\n throw new Error(`State \"${this.currentState}\" not found`);\n }\n }\n\n /** Get current state name */\n get state(): string {\n return this.currentState;\n }\n\n /** Get current frame */\n get frame(): number {\n return this.currentFrame;\n }\n\n /** Get all state names */\n get stateNames(): string[] {\n return Object.keys(this.doc.states);\n }\n\n /** Get current state duration */\n get duration(): number {\n return this.doc.states[this.currentState].duration;\n }\n\n /** Check if current state playback is complete */\n get isComplete(): boolean {\n return this.currentFrame >= this.duration - 1;\n }\n\n /** Check if currently in a transition blend */\n isTransitioning(): boolean {\n return this.activeTransition !== null;\n }\n\n /** Get transition progress (0–1) with easing applied, or null if not transitioning */\n getTransitionProgress(): number | null {\n if (!this.activeTransition) return null;\n const { transitionFrame, duration, easingFn } = this.activeTransition;\n const rawProgress = Math.min(transitionFrame / duration, 1);\n return easingFn(rawProgress);\n }\n\n // ── Hierarchical State Support ────────────────────────────\n\n /**\n * Resolve the ancestor chain for a state (root → … → parent → self).\n * Throws on circular parent references.\n */\n resolveAncestorChain(stateName: string): string[] {\n const chain: string[] = [];\n const visited = new Set<string>();\n let current: string | undefined = stateName;\n\n while (current) {\n if (visited.has(current)) {\n throw new Error(`Circular parent reference detected: \"${current}\" already in chain [${chain.join(\" → \")}]`);\n }\n visited.add(current);\n chain.unshift(current); // prepend so root is first\n const stateObj: State | undefined = this.doc.states[current];\n if (!stateObj) {\n throw new Error(`Parent state \"${current}\" not found`);\n }\n current = stateObj.parent;\n }\n\n return chain;\n }\n\n /**\n * Collect merged deltas from ancestor chain.\n * Child overrides parent deltas for the same layer+property combination.\n * Deltas for different layer+property pairs are accumulated from all ancestors.\n */\n collectDeltas(stateName: string): Delta[] {\n const chain = this.resolveAncestorChain(stateName);\n // Walk root → child. Later entries override earlier for same layer+property.\n const deltaMap = new Map<string, Delta[]>();\n\n for (const ancestorName of chain) {\n const state = this.doc.states[ancestorName];\n // Group this state's deltas by layer+property\n const stateGroups = new Map<string, Delta[]>();\n for (const delta of state.deltas) {\n const key = `${delta.layer}:${delta.property}`;\n if (!stateGroups.has(key)) stateGroups.set(key, []);\n stateGroups.get(key)!.push(delta);\n }\n // Child replaces parent for same key\n for (const [key, deltas] of stateGroups) {\n deltaMap.set(key, deltas);\n }\n }\n\n // Flatten all deltas\n const result: Delta[] = [];\n for (const deltas of deltaMap.values()) {\n result.push(...deltas);\n }\n return result;\n }\n\n // ── Playback ──────────────────────────────────────────────\n\n /** Advance to next frame, returns resolved frame */\n tick(): PlaybackState {\n // Handle active transition\n if (this.activeTransition) {\n this.activeTransition.transitionFrame++;\n if (this.activeTransition.transitionFrame >= this.activeTransition.duration) {\n // Transition complete\n this.activeTransition = null;\n }\n }\n\n const resolved = this.resolveCurrentFrame();\n const result: PlaybackState = {\n stateName: this.currentState,\n frame: this.currentFrame,\n resolved,\n isComplete: this.isComplete,\n };\n if (this.currentFrame < this.duration - 1) {\n this.currentFrame++;\n }\n return result;\n }\n\n /** Resolve the current frame, blending if in transition */\n private resolveCurrentFrame(): ResolvedFrame {\n if (this.activeTransition) {\n const progress = this.getTransitionProgress()!;\n const fromResolved = resolveFrame(\n this.doc, this.activeTransition.fromState, this.currentFrame,\n this.collectDeltas(this.activeTransition.fromState),\n );\n const toResolved = resolveFrame(\n this.doc, this.activeTransition.toState, this.currentFrame,\n this.collectDeltas(this.activeTransition.toState),\n );\n return blendResolvedFrames(fromResolved, toResolved, progress);\n }\n\n // Check if current state has a parent — use merged deltas\n const state = this.doc.states[this.currentState];\n if (state.parent) {\n const mergedDeltas = this.collectDeltas(this.currentState);\n return resolveFrame(this.doc, this.currentState, this.currentFrame, mergedDeltas);\n }\n\n return resolveFrame(this.doc, this.currentState, this.currentFrame);\n }\n\n /** Transition to a different state (instant or blended) */\n transition(stateName: string, startFrame = 0): void {\n if (!this.doc.states[stateName]) {\n throw new Error(`State \"${stateName}\" not found`);\n }\n\n const fromState = this.currentState;\n const currentStateObj = this.doc.states[fromState];\n const transConfig = currentStateObj.transitions?.[stateName];\n\n this.transitions.push({\n from: fromState,\n to: stateName,\n at: this.currentFrame,\n });\n\n if (transConfig && transConfig.duration > 0) {\n // Start a smooth transition\n this.activeTransition = {\n fromState,\n toState: stateName,\n duration: transConfig.duration,\n easingFn: resolveEasing(transConfig.easing),\n transitionFrame: 0,\n };\n }\n\n this.currentState = stateName;\n this.currentFrame = startFrame;\n }\n\n /**\n * Start a smooth transition to target state with explicit duration/easing.\n * This ignores any transitions config on the state.\n */\n transitionTo(targetState: string, duration: number, easing?: Easing): void {\n if (!this.doc.states[targetState]) {\n throw new Error(`State \"${targetState}\" not found`);\n }\n\n const fromState = this.currentState;\n this.transitions.push({\n from: fromState,\n to: targetState,\n at: this.currentFrame,\n });\n\n this.activeTransition = {\n fromState,\n toState: targetState,\n duration,\n easingFn: resolveEasing(easing),\n transitionFrame: 0,\n };\n\n this.currentState = targetState;\n this.currentFrame = 0;\n }\n\n /** Seek to a specific frame in current state */\n seek(frame: number): void {\n this.currentFrame = Math.max(0, Math.min(frame, this.duration - 1));\n }\n\n /** Reset to initial state */\n reset(stateName?: string): void {\n if (stateName) {\n if (!this.doc.states[stateName]) throw new Error(`State \"${stateName}\" not found`);\n this.currentState = stateName;\n }\n this.currentFrame = 0;\n this.activeTransition = null;\n }\n\n /** Get transition history */\n get history(): ReadonlyArray<StateTransition> {\n return this.transitions;\n }\n\n /** Resolve a specific frame without advancing */\n resolveAt(stateName: string, frame: number): ResolvedFrame {\n if (!this.doc.states[stateName]) throw new Error(`State \"${stateName}\" not found`);\n const state = this.doc.states[stateName];\n if (state.parent) {\n return resolveFrame(this.doc, stateName, frame, this.collectDeltas(stateName));\n }\n return resolveFrame(this.doc, stateName, frame);\n }\n\n /** Play through entire current state, calling callback on each frame */\n playThrough(onFrame: (state: PlaybackState) => void): void {\n this.currentFrame = 0;\n while (!this.isComplete) {\n onFrame(this.tick());\n }\n onFrame(this.tick()); // last frame\n }\n}\n\n// ── Frame Blending ────────────────────────────────────────────\n\nimport type { ResolvedLayer } from \"../resolver/frame-resolver.js\";\nimport type { AnimatableProperty } from \"@a-company/atelier-types\";\nimport { interpolateValue } from \"../resolver/delta-resolver.js\";\n\n/**\n * Blend two resolved frames together for smooth state transitions.\n * Numeric properties are lerped, colors are color-lerped, discrete values snap at t >= 0.5.\n */\nexport function blendResolvedFrames(\n frameA: ResolvedFrame,\n frameB: ResolvedFrame,\n t: number,\n): ResolvedFrame {\n // Build layer maps\n const mapA = new Map<string, ResolvedLayer>();\n const mapB = new Map<string, ResolvedLayer>();\n for (const l of frameA.layers) mapA.set(l.id, l);\n for (const l of frameB.layers) mapB.set(l.id, l);\n\n // Get all unique layer IDs\n const allIds = new Set([...mapA.keys(), ...mapB.keys()]);\n const blendedLayers: ResolvedLayer[] = [];\n\n for (const id of allIds) {\n const layerA = mapA.get(id);\n const layerB = mapB.get(id);\n\n if (layerA && layerB) {\n // Both exist — blend computed properties\n blendedLayers.push(blendLayers(layerA, layerB, t));\n } else if (layerA && !layerB) {\n // Only in A — fade out (set opacity toward 0)\n blendedLayers.push(fadeLayer(layerA, 1 - t));\n } else if (!layerA && layerB) {\n // Only in B — fade in (set opacity from 0)\n blendedLayers.push(fadeLayer(layerB, t));\n }\n }\n\n return {\n frame: frameB.frame,\n stateName: frameB.stateName,\n layers: blendedLayers,\n };\n}\n\nfunction blendLayers(a: ResolvedLayer, b: ResolvedLayer, t: number): ResolvedLayer {\n const allProps = new Set([\n ...Object.keys(a.computedProperties),\n ...Object.keys(b.computedProperties),\n ]);\n\n const blended: Partial<Record<AnimatableProperty, unknown>> = {};\n\n for (const prop of allProps) {\n const valA = a.computedProperties[prop as AnimatableProperty];\n const valB = b.computedProperties[prop as AnimatableProperty];\n\n if (valA !== undefined && valB !== undefined) {\n blended[prop as AnimatableProperty] = interpolateValue(valA, valB, t);\n } else if (valA !== undefined) {\n blended[prop as AnimatableProperty] = valA;\n } else {\n blended[prop as AnimatableProperty] = valB;\n }\n }\n\n return {\n id: a.id,\n layer: a.layer,\n computedProperties: blended,\n };\n}\n\nfunction fadeLayer(layer: ResolvedLayer, opacity: number): ResolvedLayer {\n const cp = { ...layer.computedProperties };\n const existingOpacity = (cp.opacity as number) ?? 1;\n cp.opacity = existingOpacity * opacity;\n return {\n id: layer.id,\n layer: layer.layer,\n computedProperties: cp,\n };\n}\n","import type { AtelierDocument } from \"@a-company/atelier-types\";\n\nexport interface TemplateBindings {\n [variableName: string]: unknown;\n}\n\nexport interface TemplateError {\n variable: string;\n message: string;\n}\n\nexport type TemplateResult =\n | {\n success: true;\n document: AtelierDocument;\n }\n | {\n success: false;\n errors: TemplateError[];\n };\n\n/**\n * Instantiate a template document by substituting variable values.\n * Walks the document tree, replacing {{variableName}} patterns with bound values.\n */\nexport function instantiateTemplate(\n template: AtelierDocument,\n bindings: TemplateBindings,\n): TemplateResult {\n // 1. Validate all required variables have bindings\n const errors: TemplateError[] = [];\n const variables = template.variables ?? {};\n\n for (const [name, variable] of Object.entries(variables)) {\n if (bindings[name] === undefined && variable.default === undefined) {\n errors.push({ variable: name, message: `Required variable \"${name}\" not provided` });\n }\n }\n\n // Check for unknown bindings\n for (const name of Object.keys(bindings)) {\n if (!variables[name]) {\n errors.push({ variable: name, message: `Unknown variable \"${name}\"` });\n }\n }\n\n if (errors.length > 0) return { success: false, errors };\n\n // 2. Merge bindings with defaults\n const resolved: Record<string, unknown> = {};\n for (const [name, variable] of Object.entries(variables)) {\n resolved[name] = bindings[name] ?? variable.default;\n }\n\n // 3. Deep clone and substitute\n const doc = JSON.parse(JSON.stringify(template)) as AtelierDocument;\n substituteInObject(doc as unknown as Record<string, unknown>, resolved);\n\n // 4. Remove variables section (no longer a template)\n delete doc.variables;\n\n return { success: true, document: doc };\n}\n\n/**\n * Recursively substitute {{variableName}} patterns in string values.\n */\nfunction substituteInObject(obj: Record<string, unknown>, bindings: Record<string, unknown>): void {\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (typeof value === \"string\") {\n obj[key] = substituteString(value, bindings);\n } else if (Array.isArray(value)) {\n substituteInArray(value, bindings);\n } else if (value !== null && typeof value === \"object\") {\n substituteInObject(value as Record<string, unknown>, bindings);\n }\n }\n}\n\nfunction substituteInArray(arr: unknown[], bindings: Record<string, unknown>): void {\n for (let i = 0; i < arr.length; i++) {\n const value = arr[i];\n if (typeof value === \"string\") {\n arr[i] = substituteString(value, bindings);\n } else if (Array.isArray(value)) {\n substituteInArray(value, bindings);\n } else if (value !== null && typeof value === \"object\") {\n substituteInObject(value as Record<string, unknown>, bindings);\n }\n }\n}\n\n/**\n * Replace {{variableName}} in a string with the bound value.\n * If the entire string is a single {{var}}, return the raw value (preserving type).\n * Otherwise, interpolate into the string.\n */\nfunction substituteString(str: string, bindings: Record<string, unknown>): unknown {\n // Exact match: entire string is {{varName}} -> return raw value\n const exactMatch = str.match(/^\\{\\{(\\w+)\\}\\}$/);\n if (exactMatch) {\n const name = exactMatch[1];\n return name in bindings ? bindings[name] : str;\n }\n\n // Partial match: replace all {{varName}} occurrences with string values\n return str.replace(/\\{\\{(\\w+)\\}\\}/g, (_, name: string) => {\n return name in bindings ? String(bindings[name]) : `{{${name}}}`;\n });\n}\n\n/**\n * List all variables used in a document (scan for {{variableName}} patterns).\n */\nexport function findTemplateVariables(doc: AtelierDocument): string[] {\n const vars = new Set<string>();\n scanForVariables(doc, vars);\n return Array.from(vars);\n}\n\nfunction scanForVariables(value: unknown, vars: Set<string>): void {\n if (typeof value === \"string\") {\n const matches = value.matchAll(/\\{\\{(\\w+)\\}\\}/g);\n for (const match of matches) {\n vars.add(match[1]);\n }\n } else if (Array.isArray(value)) {\n for (const item of value) scanForVariables(item, vars);\n } else if (value !== null && typeof value === \"object\") {\n for (const v of Object.values(value as Record<string, unknown>)) {\n scanForVariables(v, vars);\n }\n }\n}\n","import type { Audio } from \"@a-company/atelier-types\";\n\n/** Audio playback state at a given frame */\nexport interface AudioPlaybackState {\n /** Whether audio should be playing at this frame */\n shouldPlay: boolean;\n /** Current position in the audio track (seconds) */\n currentTime: number;\n /** Effective volume (0–1) */\n volume: number;\n}\n\n/**\n * Convert a frame number to time in seconds.\n */\nexport function frameToTime(frame: number, fps: number): number {\n return frame / fps;\n}\n\n/**\n * Convert time in seconds to a frame number (floored).\n */\nexport function timeToFrame(time: number, fps: number): number {\n return Math.floor(time * fps);\n}\n\n/**\n * Compute the audio playback state for a given frame.\n *\n * @param audio - Audio configuration from a state\n * @param frame - Current frame number within the state\n * @param fps - Frames per second from canvas config\n * @param stateDuration - Total state duration in frames\n * @returns AudioPlaybackState with shouldPlay, currentTime, and volume\n */\nexport function computeAudioState(\n audio: Audio,\n frame: number,\n fps: number,\n stateDuration: number,\n): AudioPlaybackState {\n const startFrame = audio.startFrame ?? 0;\n const offset = audio.offset ?? 0;\n const volume = audio.volume ?? 1;\n const loop = audio.loop ?? false;\n\n // Before audio starts\n if (frame < startFrame) {\n return { shouldPlay: false, currentTime: 0, volume };\n }\n\n // Time elapsed since audio started\n const elapsedFrames = frame - startFrame;\n const elapsedTime = frameToTime(elapsedFrames, fps);\n\n // Total available playback time (from startFrame to end of state)\n const availableFrames = stateDuration - startFrame;\n const availableTime = frameToTime(availableFrames, fps);\n\n if (!loop) {\n // Non-looping: audio plays from offset, stops at end of state\n const currentTime = offset + elapsedTime;\n return {\n shouldPlay: frame < stateDuration,\n currentTime,\n volume,\n };\n }\n\n // Looping: wrap elapsed time around available duration\n // The audio segment length is the available time\n const segmentDuration = availableTime;\n if (segmentDuration <= 0) {\n return { shouldPlay: false, currentTime: 0, volume };\n }\n\n const wrappedTime = elapsedTime % segmentDuration;\n const currentTime = offset + wrappedTime;\n\n return {\n shouldPlay: frame < stateDuration,\n currentTime,\n volume,\n };\n}\n\n/**\n * Compute audio cue points — frames where audio events occur.\n *\n * @param audio - Audio configuration\n * @param stateDuration - Total state duration in frames\n * @returns Array of { frame, event } describing audio events\n */\nexport function computeAudioCues(\n audio: Audio,\n stateDuration: number,\n): Array<{ frame: number; event: \"start\" | \"end\" | \"loop\" }> {\n const startFrame = audio.startFrame ?? 0;\n const loop = audio.loop ?? false;\n const cues: Array<{ frame: number; event: \"start\" | \"end\" | \"loop\" }> = [];\n\n if (startFrame < stateDuration) {\n cues.push({ frame: startFrame, event: \"start\" });\n }\n\n if (loop) {\n // In loop mode, audio restarts each full cycle\n const availableFrames = stateDuration - startFrame;\n if (availableFrames > 0) {\n // Loop points at each full cycle\n for (let i = 1; startFrame + i * availableFrames < stateDuration; i++) {\n cues.push({ frame: startFrame + i * availableFrames, event: \"loop\" });\n }\n }\n }\n\n // Audio ends when state ends\n if (stateDuration > startFrame) {\n cues.push({ frame: stateDuration - 1, event: \"end\" });\n }\n\n return cues;\n}\n","// @a-company/atelier-mcp — Preset management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Preset, PresetDelta } from \"@a-company/atelier-types\";\nimport { AnimatablePropertySchema, EasingSchema } from \"@a-company/atelier-schema\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\n// Canonical source: @a-company/atelier-schema — single source of truth for AnimatableProperty\nconst AnimatablePropertyEnum = AnimatablePropertySchema;\nconst EasingInputSchema = EasingSchema;\n\nconst PresetDeltaSchema = z.object({\n property: AnimatablePropertyEnum.describe(\"Animatable property\"),\n offset: z.tuple([z.number().int().min(0), z.number().int().min(0)]).optional().describe(\"Relative frame offset [start, end]\"),\n from: z.unknown().describe(\"Starting value\"),\n to: z.unknown().describe(\"Ending value\"),\n easing: EasingInputSchema.optional().describe(\"Easing function\"),\n});\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_define_preset ───────────────────────────────────\n server.tool(\n \"atelier_define_preset\",\n \"Define a reusable animation preset on a document\",\n {\n id: z.string().describe(\"Document ID\"),\n presetName: z.string().describe(\"Preset name\"),\n description: z.string().optional().describe(\"Preset description\"),\n tags: z.array(z.string()).optional().describe(\"Tags\"),\n deltas: z.array(PresetDeltaSchema).min(1).describe(\"Array of preset delta definitions\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, presetName, description, tags, deltas }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.presets) doc.presets = {};\n\n const preset: Preset = {\n deltas: deltas as unknown as PresetDelta[],\n ...(description ? { description } : {}),\n ...(tags ? { tags } : {}),\n };\n\n doc.presets[presetName] = preset;\n\n return ok({ presetName, deltaCount: deltas.length });\n },\n );\n\n // ── atelier_list_presets ────────────────────────────────────\n server.tool(\n \"atelier_list_presets\",\n \"List all presets defined on a document\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.presets || Object.keys(doc.presets).length === 0) {\n return ok({ presets: [], count: 0 });\n }\n\n const presets = Object.entries(doc.presets).map(([name, preset]) => ({\n name,\n description: preset.description,\n tags: preset.tags,\n deltaCount: preset.deltas.length,\n properties: preset.deltas.map(d => d.property),\n }));\n\n return ok({ presets, count: presets.length });\n },\n );\n}\n","// @a-company/atelier-mcp — Validation and preview tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { validateDocument } from \"@a-company/atelier-schema\";\nimport { validateAllDeltas, resolveFrame } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_validate ────────────────────────────────────────\n server.tool(\n \"atelier_validate\",\n \"Validate an Atelier document for schema correctness and delta overlaps\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n // Schema validation\n const schemaResult = validateDocument(doc);\n const schemaErrors = schemaResult.success ? [] : schemaResult.errors;\n\n // Overlap validation per state\n const overlapErrors: Array<{ state: string; message: string }> = [];\n for (const [stateName, state] of Object.entries(doc.states)) {\n const overlaps = validateAllDeltas(state.deltas);\n for (const overlap of overlaps) {\n overlapErrors.push({ state: stateName, message: overlap.message });\n }\n }\n\n const valid = schemaErrors.length === 0 && overlapErrors.length === 0;\n\n return ok({\n valid,\n schemaErrors,\n overlapErrors,\n summary: valid\n ? \"Document is valid\"\n : `Found ${schemaErrors.length} schema error(s) and ${overlapErrors.length} overlap error(s)`,\n });\n },\n );\n\n // ── atelier_preview ─────────────────────────────────────────\n server.tool(\n \"atelier_preview\",\n \"Preview the resolved state of all layers at a specific frame\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to preview\"),\n frame: z.number().int().min(0).describe(\"Frame number to resolve\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frame }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) {\n return err(`State \"${stateName}\" not found`);\n }\n\n try {\n const resolved = resolveFrame(doc, stateName, frame);\n\n const layers = resolved.layers.map(rl => ({\n id: rl.id,\n visualType: rl.layer.visual.type,\n baseFrame: rl.layer.frame,\n baseBounds: rl.layer.bounds,\n baseOpacity: rl.layer.opacity,\n baseRotation: rl.layer.rotation,\n computedProperties: rl.computedProperties,\n }));\n\n return ok({\n stateName: resolved.stateName,\n frame: resolved.frame,\n duration: doc.states[stateName].duration,\n layers,\n });\n } catch (e) {\n return err(`Preview failed: ${(e as Error).message}`);\n }\n },\n );\n}\n","// @a-company/atelier-mcp — Template variable tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { instantiateTemplate, findTemplateVariables } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_instantiate_template ──────────────────────────────\n server.tool(\n \"atelier_instantiate_template\",\n \"Instantiate a template document with variable bindings. Creates a new document in the store.\",\n {\n id: z.string().describe(\"Template document ID\"),\n bindings: z.record(z.unknown()).describe(\"Variable bindings: { variableName: value }\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, bindings }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const templateResult = instantiateTemplate(doc, bindings);\n\n if (!templateResult.success) {\n return err(`Template errors: ${templateResult.errors.map(e => `${e.variable}: ${e.message}`).join(\"; \")}`);\n }\n\n const newId = store.create(templateResult.document);\n return ok({\n id: newId,\n name: templateResult.document.name,\n message: \"Template instantiated successfully\",\n });\n },\n );\n\n // ── atelier_find_variables ────────────────────────────────────\n server.tool(\n \"atelier_find_variables\",\n \"Scan a document for {{variableName}} patterns. Returns the list of variable references found.\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const variables = findTemplateVariables(doc);\n const declared = doc.variables ? Object.keys(doc.variables) : [];\n\n return ok({\n variables,\n declared,\n undeclared: variables.filter(v => !declared.includes(v)),\n unused: declared.filter(d => !variables.includes(d)),\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Layer effect tools (blend mode, shadow, motion path, clip path, visual editing)\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n AtelierDocument,\n ShapeVisual,\n TextVisual,\n ImageVisual,\n} from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_set_blend_mode ────────────────────────────────\n server.tool(\n \"atelier_set_blend_mode\",\n \"Set or clear the blend mode on a layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n blendMode: z.enum([\n \"normal\", \"multiply\", \"screen\", \"overlay\", \"darken\", \"lighten\",\n \"color-dodge\", \"color-burn\", \"hard-light\", \"soft-light\",\n \"difference\", \"exclusion\", \"hue\", \"saturation\", \"color\", \"luminosity\",\n ]).nullable().describe(\"Blend mode to set, or null to clear\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, blendMode }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (blendMode === null) {\n delete layer.blendMode;\n return ok({ layerId, blendMode: null, cleared: true });\n }\n\n layer.blendMode = blendMode;\n return ok({ layerId, blendMode });\n },\n );\n\n // ── atelier_set_shadow ────────────────────────────────────\n server.tool(\n \"atelier_set_shadow\",\n \"Set or remove a drop shadow on a layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n shadow: z.object({\n color: z.unknown().describe(\"Shadow color (hex string or RGBA/HSLA object)\"),\n blur: z.number().min(0).describe(\"Blur radius in pixels\"),\n offsetX: z.number().optional().describe(\"Horizontal offset in pixels\"),\n offsetY: z.number().optional().describe(\"Vertical offset in pixels\"),\n }).nullable().describe(\"Shadow definition, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, shadow }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (shadow === null) {\n delete layer.shadow;\n return ok({ layerId, shadow: null, removed: true });\n }\n\n layer.shadow = shadow as unknown as NonNullable<typeof layer.shadow>;\n return ok({ layerId, hasShadow: true });\n },\n );\n\n // ── atelier_set_tint ─────────────────────────────────────\n server.tool(\n \"atelier_set_tint\",\n \"Set or remove a color tint on a layer (works on any visual type)\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n tint: z.object({\n color: z.string().describe(\"Tint color (hex string)\"),\n amount: z.number().min(0).max(1).describe(\"Tint amount (0 = none, 1 = full)\"),\n }).nullable().describe(\"Tint definition, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, tint }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (tint === null) {\n delete layer.tint;\n return ok({ layerId, tint: null, removed: true });\n }\n\n layer.tint = tint;\n return ok({ layerId, hasTint: true });\n },\n );\n\n // ── atelier_set_motion_path ───────────────────────────────\n server.tool(\n \"atelier_set_motion_path\",\n \"Set or remove a motion path on a layer for path-based position animation\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n motionPath: z.object({\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).min(2).describe(\"Path points (minimum 2)\"),\n closed: z.boolean().optional().describe(\"Whether the path is closed\"),\n autoRotate: z.boolean().optional().describe(\"Auto-rotate layer to follow path tangent\"),\n autoRotateOffset: z.number().optional().describe(\"Rotation offset in degrees when autoRotate is enabled\"),\n }).nullable().describe(\"Motion path definition, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, motionPath }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (motionPath === null) {\n delete layer.motionPath;\n return ok({ layerId, motionPath: null, removed: true });\n }\n\n layer.motionPath = motionPath as unknown as NonNullable<typeof layer.motionPath>;\n return ok({ layerId, pointCount: motionPath.points.length, closed: motionPath.closed ?? false });\n },\n );\n\n // ── atelier_set_clip_path ─────────────────────────────────\n server.tool(\n \"atelier_set_clip_path\",\n \"Set or remove a clip path on a layer to restrict rendering to within a shape\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n clipPath: z.object({\n type: z.enum([\"rect\", \"ellipse\", \"path\"]).describe(\"Clip shape type\"),\n cornerRadius: z.union([\n z.number(),\n z.tuple([z.number(), z.number(), z.number(), z.number()]),\n ]).optional().describe(\"Corner radius (rect only)\"),\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).optional().describe(\"Path points (path only)\"),\n closed: z.boolean().optional().describe(\"Whether path is closed (path only)\"),\n }).nullable().describe(\"Clip path shape, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, clipPath }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (clipPath === null) {\n delete layer.clipPath;\n return ok({ layerId, clipPath: null, removed: true });\n }\n\n layer.clipPath = clipPath as unknown as NonNullable<typeof layer.clipPath>;\n return ok({ layerId, clipType: clipPath.type });\n },\n );\n\n // ── atelier_edit_visual ───────────────────────────────────\n server.tool(\n \"atelier_edit_visual\",\n \"Edit visual content of an existing layer (text content/style, image src/assetId, shape/fill/stroke)\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n // Text fields\n content: z.string().optional().describe(\"New text content (text layers only)\"),\n style: z.record(z.unknown()).optional().describe(\"Partial style update — only provided keys are overwritten (text layers only)\"),\n // Image fields\n src: z.string().optional().describe(\"Image source URL (image layers only)\"),\n assetId: z.string().optional().describe(\"Asset ID reference (image layers only)\"),\n sourceRect: z.object({\n x: z.number(), y: z.number(), width: z.number().positive(), height: z.number().positive(),\n }).nullable().optional().describe(\"Source rectangle crop (image layers only). Null to remove.\"),\n spritesheet: z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n }).nullable().optional().describe(\"Spritesheet config (image layers only). Null to remove.\"),\n frameIndex: z.number().int().min(0).optional().describe(\"Spritesheet frame index (image layers only)\"),\n // Shape fields\n shape: z.object({\n type: z.enum([\"rect\", \"ellipse\", \"path\"]),\n cornerRadius: z.union([\n z.number(),\n z.tuple([z.number(), z.number(), z.number(), z.number()]),\n ]).optional(),\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).optional(),\n closed: z.boolean().optional(),\n }).optional().describe(\"New shape (shape layers only)\"),\n fill: z.record(z.unknown()).optional().describe(\"New fill definition (shape layers only)\"),\n stroke: z.record(z.unknown()).optional().describe(\"New stroke definition (shape layers only)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, content, style, src, assetId, sourceRect, spritesheet, frameIndex, shape, fill, stroke }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n const visualType = layer.visual.type;\n const updated: string[] = [];\n\n // Text fields\n if (content !== undefined) {\n if (visualType !== \"text\") return err(`Cannot set \"content\" on ${visualType} layer — text layers only`);\n (layer.visual as TextVisual).content = content;\n updated.push(\"content\");\n }\n if (style !== undefined) {\n if (visualType !== \"text\") return err(`Cannot set \"style\" on ${visualType} layer — text layers only`);\n const currentStyle = (layer.visual as TextVisual).style;\n Object.assign(currentStyle, style);\n updated.push(\"style\");\n }\n\n // Image fields\n if (src !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"src\" on ${visualType} layer — image layers only`);\n (layer.visual as ImageVisual).src = src;\n updated.push(\"src\");\n }\n if (assetId !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"assetId\" on ${visualType} layer — image layers only`);\n (layer.visual as ImageVisual).assetId = assetId;\n updated.push(\"assetId\");\n }\n if (sourceRect !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"sourceRect\" on ${visualType} layer — image layers only`);\n if (sourceRect === null) {\n delete (layer.visual as ImageVisual).sourceRect;\n updated.push(\"sourceRect (removed)\");\n } else {\n (layer.visual as ImageVisual).sourceRect = sourceRect;\n updated.push(\"sourceRect\");\n }\n }\n if (spritesheet !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"spritesheet\" on ${visualType} layer — image layers only`);\n if (spritesheet === null) {\n delete (layer.visual as ImageVisual).spritesheet;\n updated.push(\"spritesheet (removed)\");\n } else {\n (layer.visual as ImageVisual).spritesheet = spritesheet;\n updated.push(\"spritesheet\");\n }\n }\n if (frameIndex !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"frameIndex\" on ${visualType} layer — image layers only`);\n (layer.visual as ImageVisual).frameIndex = frameIndex;\n updated.push(\"frameIndex\");\n }\n\n // Shape fields\n if (shape !== undefined) {\n if (visualType !== \"shape\") return err(`Cannot set \"shape\" on ${visualType} layer — shape layers only`);\n (layer.visual as ShapeVisual).shape = shape as ShapeVisual[\"shape\"];\n updated.push(\"shape\");\n }\n if (fill !== undefined) {\n if (visualType !== \"shape\") return err(`Cannot set \"fill\" on ${visualType} layer — shape layers only`);\n (layer.visual as ShapeVisual).fill = fill as unknown as ShapeVisual[\"fill\"];\n updated.push(\"fill\");\n }\n if (stroke !== undefined) {\n if (visualType !== \"shape\") return err(`Cannot set \"stroke\" on ${visualType} layer — shape layers only`);\n (layer.visual as ShapeVisual).stroke = stroke as unknown as ShapeVisual[\"stroke\"];\n updated.push(\"stroke\");\n }\n\n if (updated.length === 0) {\n return err(\"No visual fields provided to update\");\n }\n\n return ok({ layerId, visualType, updated });\n },\n );\n}\n","// @a-company/atelier-mcp — State configuration tools (audio, transitions, parent states)\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nconst EasingInputSchema = z.union([\n z.enum([\"ease-in\", \"ease-out\", \"ease-in-out\"]),\n z.object({ type: z.literal(\"linear\") }),\n z.object({\n type: z.literal(\"cubic-bezier\"),\n x1: z.number(), y1: z.number(), x2: z.number(), y2: z.number(),\n }),\n z.object({\n type: z.literal(\"spring\"),\n mass: z.number().optional(),\n stiffness: z.number().optional(),\n damping: z.number().optional(),\n velocity: z.number().optional(),\n }),\n z.object({\n type: z.literal(\"step\"),\n steps: z.number().int().positive(),\n position: z.enum([\"start\", \"end\"]).optional(),\n }),\n]).describe(\"Easing function\");\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_set_audio ─────────────────────────────────────\n server.tool(\n \"atelier_set_audio\",\n \"Set or remove an audio track on a state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n audio: z.object({\n src: z.string().describe(\"Audio source — asset reference, file path, or URL\"),\n offset: z.number().min(0).optional().describe(\"Skip into audio in seconds (default: 0)\"),\n volume: z.number().min(0).max(1).optional().describe(\"Playback volume 0–1 (default: 1)\"),\n loop: z.boolean().optional().describe(\"Loop for state duration (default: false)\"),\n startFrame: z.number().int().min(0).optional().describe(\"Frame to start playing (default: 0)\"),\n }).nullable().describe(\"Audio configuration, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, audio }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (audio === null) {\n delete state.audio;\n return ok({ stateName, audio: null, removed: true });\n }\n\n state.audio = audio;\n return ok({ stateName, audioSrc: audio.src });\n },\n );\n\n // ── atelier_configure_transition ──────────────────────────\n server.tool(\n \"atelier_configure_transition\",\n \"Configure or remove a transition from one state to a target state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"Source state name\"),\n targetState: z.string().describe(\"Target state name\"),\n transition: z.object({\n duration: z.number().positive().int().describe(\"Transition duration in frames\"),\n easing: EasingInputSchema.optional(),\n }).nullable().describe(\"Transition config, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, targetState, transition }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (stateName === targetState) {\n return err(\"Cannot create a transition from a state to itself\");\n }\n\n if (!doc.states[targetState]) {\n return err(`Target state \"${targetState}\" not found`);\n }\n\n if (transition === null) {\n if (state.transitions) {\n delete state.transitions[targetState];\n if (Object.keys(state.transitions).length === 0) {\n delete state.transitions;\n }\n }\n return ok({ stateName, targetState, removed: true });\n }\n\n if (!state.transitions) {\n state.transitions = {};\n }\n state.transitions[targetState] = transition as unknown as NonNullable<typeof state.transitions>[string];\n return ok({ stateName, targetState, duration: transition.duration });\n },\n );\n\n // ── atelier_set_state_parent ──────────────────────────────\n server.tool(\n \"atelier_set_state_parent\",\n \"Set or clear the parent state for hierarchical delta inheritance\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n parent: z.string().nullable().describe(\"Parent state name, or null to clear\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, parent }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (parent === null) {\n delete state.parent;\n return ok({ stateName, parent: null, cleared: true });\n }\n\n if (parent === stateName) {\n return err(\"A state cannot be its own parent\");\n }\n\n if (!doc.states[parent]) {\n return err(`Parent state \"${parent}\" not found`);\n }\n\n // Walk parent chain to detect cycles\n let current = parent;\n const visited = new Set<string>([stateName]);\n while (current) {\n if (visited.has(current)) {\n return err(`Circular reference detected: setting parent \"${parent}\" would create a cycle`);\n }\n visited.add(current);\n current = doc.states[current]?.parent as string;\n }\n\n state.parent = parent;\n return ok({ stateName, parent });\n },\n );\n}\n","// @a-company/atelier-mcp — Export tools (SVG, Lottie)\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { renderFrameSVG } from \"@a-company/atelier-svg\";\nimport { exportToLottie } from \"@a-company/atelier-lottie\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_export_svg ────────────────────────────────────\n server.tool(\n \"atelier_export_svg\",\n \"Export a frame as an SVG string\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().optional().describe(\"State name (defaults to first state)\"),\n frame: z.number().int().min(0).optional().describe(\"Frame number (defaults to 0)\"),\n xmlDeclaration: z.boolean().optional().describe(\"Include XML declaration (default: false)\"),\n viewBox: z.boolean().optional().describe(\"Include viewBox attribute (default: true)\"),\n indent: z.number().int().min(0).optional().describe(\"Indent size in spaces (default: 2)\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frame, xmlDeclaration, viewBox, indent }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) {\n return err(\"Document has no states\");\n }\n\n const resolvedStateName = stateName ?? stateNames[0];\n if (!doc.states[resolvedStateName]) {\n return err(`State \"${resolvedStateName}\" not found`);\n }\n\n try {\n const svg = renderFrameSVG(doc, resolvedStateName, frame ?? 0, {\n xmlDeclaration,\n viewBox,\n indent,\n });\n return ok({ svg, stateName: resolvedStateName, frame: frame ?? 0 });\n } catch (e) {\n return err((e as Error).message);\n }\n },\n );\n\n // ── atelier_export_lottie ─────────────────────────────────\n server.tool(\n \"atelier_export_lottie\",\n \"Export a document to Lottie JSON format (lossy, best-effort)\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().optional().describe(\"State to export (defaults to first state)\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n try {\n const { json, warnings } = exportToLottie(doc, {\n state: stateName,\n });\n return ok({ lottie: json as unknown as Record<string, unknown>, warnings });\n } catch (e) {\n return err((e as Error).message);\n }\n },\n );\n}\n","import type { Fill, Stroke, Color, RGBAColor, HSLAColor } from \"@a-company/atelier-types\";\nimport type { RenderContext } from \"./canvas-types.js\";\n\n/**\n * Convert an Atelier Color to a CSS color string.\n */\nexport function colorToCSS(color: Color): string {\n if (typeof color === \"string\") return color; // hex string\n\n if (\"r\" in color) {\n const c = color as RGBAColor;\n return `rgba(${Math.round(c.r)}, ${Math.round(c.g)}, ${Math.round(c.b)}, ${c.a})`;\n }\n\n if (\"h\" in color) {\n const c = color as HSLAColor;\n return `hsla(${c.h}, ${c.s}%, ${c.l}%, ${c.a})`;\n }\n\n return \"#000000\";\n}\n\n/**\n * Apply a Fill to the canvas context's fillStyle.\n */\nexport function applyFill(ctx: RenderContext, fill: Fill, width: number, height: number): void {\n switch (fill.type) {\n case \"solid\":\n ctx.fillStyle = colorToCSS(fill.color);\n break;\n\n case \"linear-gradient\": {\n const rad = (fill.angle * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const halfW = width / 2;\n const halfH = height / 2;\n const grad = ctx.createLinearGradient(\n halfW - cos * halfW, halfH - sin * halfH,\n halfW + cos * halfW, halfH + sin * halfH,\n );\n for (const stop of fill.stops) {\n grad.addColorStop(stop.offset, colorToCSS(stop.color));\n }\n ctx.fillStyle = grad as unknown as string;\n break;\n }\n\n case \"radial-gradient\": {\n const cx = typeof fill.center.x === \"number\" ? fill.center.x : (parseFloat(fill.center.x) / 100) * width;\n const cy = typeof fill.center.y === \"number\" ? fill.center.y : (parseFloat(fill.center.y) / 100) * height;\n const r = typeof fill.radius === \"number\" ? fill.radius : (parseFloat(fill.radius) / 100) * Math.max(width, height);\n const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, r);\n for (const stop of fill.stops) {\n grad.addColorStop(stop.offset, colorToCSS(stop.color));\n }\n ctx.fillStyle = grad as unknown as string;\n break;\n }\n }\n}\n\n/**\n * Apply a Stroke to the canvas context.\n * @param pathLength - total perimeter of the shape (needed for strokeStart/strokeEnd trim)\n */\nexport function applyStroke(ctx: RenderContext, stroke: Stroke, pathLength: number): void {\n ctx.strokeStyle = colorToCSS(stroke.color);\n ctx.lineWidth = stroke.width;\n if (stroke.lineCap) ctx.lineCap = stroke.lineCap;\n if (stroke.lineJoin) ctx.lineJoin = stroke.lineJoin;\n\n const start = stroke.strokeStart ?? 0;\n const end = stroke.strokeEnd ?? 1;\n\n if (start !== 0 || end !== 1) {\n const visible = (end - start) * pathLength;\n ctx.setLineDash([Math.max(visible, 0), pathLength + 1]);\n ctx.lineDashOffset = -start * pathLength;\n } else if (stroke.dash) {\n ctx.setLineDash(stroke.dash);\n }\n}\n","import type { Layer, Visual, ShapeVisual, TextVisual, ImageVisual, Color, BlendMode, LinearGradientFill, RadialGradientFill } from \"@a-company/atelier-types\";\nimport { colorToCSS } from \"./styles.js\";\nimport { evaluatePathAtProgress } from \"@a-company/atelier-math\";\nimport type { ResolvedLayer } from \"@a-company/atelier-core\";\n\n/**\n * Effective values for a layer at a given frame,\n * with computed properties merged over defaults.\n */\nexport interface EffectiveLayer {\n /** Original layer */\n layer: Layer;\n /** Visual with animated property overrides applied */\n visual: Visual;\n /** Effective frame position (may be animated) */\n x: number;\n y: number;\n /** Effective bounds */\n width: number;\n height: number;\n /** Effective transform values */\n opacity: number;\n rotation: number;\n scaleX: number;\n scaleY: number;\n anchorX: number;\n anchorY: number;\n /** Resolved shadow (if layer has shadow or shadow is animated) */\n shadow?: {\n color: string;\n blur: number;\n offsetX: number;\n offsetY: number;\n };\n /** Blend mode for compositing */\n blendMode: string;\n /** Motion path auto-rotation in degrees (applied additively to rotation) */\n motionPathAngle: number;\n /** Whether this layer is visible (may be animated) */\n visible: boolean;\n /** Color tint overlay */\n tint?: {\n color: string;\n amount: number;\n };\n}\n\n/**\n * Resolve a UnitValue to pixels. Percentages resolve against a reference dimension.\n */\nfunction resolveUnit(value: number | string, reference: number): number {\n if (typeof value === \"string\" && value.endsWith(\"%\")) {\n return (parseFloat(value) / 100) * reference;\n }\n return value as number;\n}\n\n/**\n * Build the effective layer values by merging computed properties over layer defaults.\n * @param resolved - The resolved layer from frame resolution\n * @param parentWidth - Parent/canvas width for percentage resolution\n * @param parentHeight - Parent/canvas height for percentage resolution\n */\nexport function buildEffectiveLayer(\n resolved: ResolvedLayer,\n parentWidth: number,\n parentHeight: number,\n): EffectiveLayer {\n const { layer, computedProperties } = resolved;\n const cp = computedProperties as Record<string, unknown>;\n\n const hasShadow = layer.shadow || cp[\"shadow.blur\"] !== undefined || cp[\"shadow.color\"] !== undefined;\n const hasTint = layer.tint || cp[\"tint.amount\"] !== undefined || cp[\"tint.color\"] !== undefined;\n\n // Resolve base position\n let x = resolveUnit((cp[\"frame.x\"] ?? layer.frame.x) as number | string, parentWidth);\n let y = resolveUnit((cp[\"frame.y\"] ?? layer.frame.y) as number | string, parentHeight);\n let motionPathAngle = 0;\n\n // Motion path overrides position when progress is animated\n const motionProgress = cp[\"motionPath.progress\"] as number | undefined;\n if (motionProgress !== undefined && layer.motionPath && layer.motionPath.points.length >= 2) {\n const pos = evaluatePathAtProgress(layer.motionPath.points, motionProgress, layer.motionPath.closed);\n x = pos.x;\n y = pos.y;\n if (layer.motionPath.autoRotate) {\n motionPathAngle = pos.angle + (layer.motionPath.autoRotateOffset ?? 0);\n }\n }\n\n return {\n layer,\n visual: buildEffectiveVisual(layer.visual, cp),\n x,\n y,\n width: resolveUnit((cp[\"bounds.width\"] ?? layer.bounds.width) as number | string, parentWidth),\n height: resolveUnit((cp[\"bounds.height\"] ?? layer.bounds.height) as number | string, parentHeight),\n opacity: (cp[\"opacity\"] as number) ?? layer.opacity ?? 1,\n rotation: (cp[\"rotation\"] as number) ?? layer.rotation ?? 0,\n scaleX: (cp[\"scale.x\"] as number) ?? layer.scale?.x ?? 1,\n scaleY: (cp[\"scale.y\"] as number) ?? layer.scale?.y ?? 1,\n anchorX: (cp[\"anchorPoint.x\"] as number) ?? layer.anchorPoint?.x ?? 0,\n anchorY: (cp[\"anchorPoint.y\"] as number) ?? layer.anchorPoint?.y ?? 0,\n shadow: hasShadow ? {\n color: colorToCSS((cp[\"shadow.color\"] ?? layer.shadow?.color ?? \"#00000080\") as Color),\n blur: (cp[\"shadow.blur\"] as number) ?? layer.shadow?.blur ?? 0,\n offsetX: (cp[\"shadow.offsetX\"] as number) ?? layer.shadow?.offsetX ?? 0,\n offsetY: (cp[\"shadow.offsetY\"] as number) ?? layer.shadow?.offsetY ?? 0,\n } : undefined,\n blendMode: (layer.blendMode as BlendMode) ?? \"normal\",\n motionPathAngle,\n visible: (cp[\"visible\"] as boolean) ?? layer.visible ?? true,\n tint: hasTint ? {\n color: colorToCSS((cp[\"tint.color\"] ?? layer.tint?.color ?? \"#FF0000\") as Color),\n amount: (cp[\"tint.amount\"] as number) ?? layer.tint?.amount ?? 0,\n } : undefined,\n };\n}\n\n/**\n * Build an effective visual by applying computed property overrides.\n * Returns the original visual if no visual properties are animated.\n */\nfunction buildEffectiveVisual(visual: Visual, cp: Record<string, unknown>): Visual {\n const hasVisualOverride =\n cp[\"visual.fill.color\"] !== undefined ||\n cp[\"visual.fill.angle\"] !== undefined ||\n cp[\"visual.fill.center.x\"] !== undefined ||\n cp[\"visual.fill.center.y\"] !== undefined ||\n cp[\"visual.fill.radius\"] !== undefined ||\n cp[\"visual.stroke.color\"] !== undefined ||\n cp[\"visual.stroke.width\"] !== undefined ||\n cp[\"visual.stroke.start\"] !== undefined ||\n cp[\"visual.stroke.end\"] !== undefined ||\n cp[\"visual.shape.cornerRadius\"] !== undefined ||\n cp[\"visual.style.fontSize\"] !== undefined ||\n cp[\"visual.style.color\"] !== undefined;\n\n const hasImageOverride =\n cp[\"visual.image.sourceRect.x\"] !== undefined ||\n cp[\"visual.image.sourceRect.y\"] !== undefined ||\n cp[\"visual.image.sourceRect.width\"] !== undefined ||\n cp[\"visual.image.sourceRect.height\"] !== undefined ||\n cp[\"visual.image.frameIndex\"] !== undefined;\n\n if (!hasVisualOverride && !hasImageOverride) return visual;\n\n if (visual.type === \"shape\") {\n const v: ShapeVisual = { ...visual };\n\n if (cp[\"visual.shape.cornerRadius\"] !== undefined && v.shape.type === \"rect\") {\n v.shape = { ...v.shape, cornerRadius: cp[\"visual.shape.cornerRadius\"] as number };\n }\n\n if (v.fill) {\n if (cp[\"visual.fill.color\"] !== undefined && v.fill.type === \"solid\") {\n v.fill = { ...v.fill, color: cp[\"visual.fill.color\"] as string };\n }\n if (cp[\"visual.fill.angle\"] !== undefined && v.fill.type === \"linear-gradient\") {\n v.fill = { ...v.fill, angle: cp[\"visual.fill.angle\"] as number } as LinearGradientFill;\n }\n if (v.fill.type === \"radial-gradient\") {\n const cx = cp[\"visual.fill.center.x\"];\n const cy = cp[\"visual.fill.center.y\"];\n const r = cp[\"visual.fill.radius\"];\n if (cx !== undefined || cy !== undefined || r !== undefined) {\n const f = v.fill as RadialGradientFill;\n v.fill = {\n ...f,\n center: {\n x: cx !== undefined ? (cx as number) : f.center.x,\n y: cy !== undefined ? (cy as number) : f.center.y,\n },\n radius: r !== undefined ? (r as number) : f.radius,\n } as RadialGradientFill;\n }\n }\n }\n\n if (v.stroke) {\n const strokeColor = cp[\"visual.stroke.color\"] ?? v.stroke.color;\n const strokeWidth = (cp[\"visual.stroke.width\"] as number) ?? v.stroke.width;\n const strokeStart = (cp[\"visual.stroke.start\"] as number | undefined) ?? v.stroke.strokeStart;\n const strokeEnd = (cp[\"visual.stroke.end\"] as number | undefined) ?? v.stroke.strokeEnd;\n if (\n strokeColor !== v.stroke.color ||\n strokeWidth !== v.stroke.width ||\n strokeStart !== v.stroke.strokeStart ||\n strokeEnd !== v.stroke.strokeEnd\n ) {\n v.stroke = {\n ...v.stroke,\n color: strokeColor as string,\n width: strokeWidth,\n strokeStart,\n strokeEnd,\n };\n }\n }\n\n return v;\n }\n\n if (visual.type === \"text\") {\n const v: TextVisual = { ...visual };\n const fontSize = (cp[\"visual.style.fontSize\"] as number) ?? v.style.fontSize;\n const color = cp[\"visual.style.color\"] ?? v.style.color;\n if (fontSize !== v.style.fontSize || color !== v.style.color) {\n v.style = { ...v.style, fontSize, color: color as string };\n }\n return v;\n }\n\n if (visual.type === \"image\" && hasImageOverride) {\n const v: ImageVisual = { ...visual };\n\n // Merge animated sourceRect fields\n if (\n cp[\"visual.image.sourceRect.x\"] !== undefined ||\n cp[\"visual.image.sourceRect.y\"] !== undefined ||\n cp[\"visual.image.sourceRect.width\"] !== undefined ||\n cp[\"visual.image.sourceRect.height\"] !== undefined\n ) {\n const base = v.sourceRect ?? { x: 0, y: 0, width: 0, height: 0 };\n v.sourceRect = {\n x: (cp[\"visual.image.sourceRect.x\"] as number) ?? base.x,\n y: (cp[\"visual.image.sourceRect.y\"] as number) ?? base.y,\n width: (cp[\"visual.image.sourceRect.width\"] as number) ?? base.width,\n height: (cp[\"visual.image.sourceRect.height\"] as number) ?? base.height,\n };\n }\n\n // Merge animated frameIndex\n if (cp[\"visual.image.frameIndex\"] !== undefined) {\n v.frameIndex = Math.floor(cp[\"visual.image.frameIndex\"] as number);\n }\n\n return v;\n }\n\n return visual;\n}\n","import type { ShapeVisual } from \"@a-company/atelier-types\";\nimport type { RenderContext } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\nimport { applyFill, applyStroke } from \"../styles.js\";\n\nexport function renderShape(ctx: RenderContext, eff: EffectiveLayer): void {\n const visual = eff.visual as ShapeVisual;\n const { shape } = visual;\n const { width, height } = eff;\n\n switch (shape.type) {\n case \"rect\":\n renderRect(ctx, width, height, shape.cornerRadius, visual);\n break;\n case \"ellipse\":\n renderEllipse(ctx, width, height, visual);\n break;\n case \"path\":\n renderPath(ctx, shape.points, shape.closed, visual);\n break;\n }\n}\n\n// ── Perimeter helpers ───────────────────────────────────────\n\nfunction rectPerimeter(w: number, h: number): number {\n return 2 * (w + h);\n}\n\nfunction ellipsePerimeter(w: number, h: number): number {\n const a = w / 2;\n const b = h / 2;\n // Ramanujan approximation\n return Math.PI * (3 * (a + b) - Math.sqrt((3 * a + b) * (a + 3 * b)));\n}\n\nfunction dist(x1: number, y1: number, x2: number, y2: number): number {\n const dx = x2 - x1;\n const dy = y2 - y1;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\nfunction pathPerimeter(\n points: { x: number; y: number; in?: { x: number; y: number }; out?: { x: number; y: number } }[],\n closed: boolean | undefined,\n): number {\n let length = 0;\n for (let i = 1; i < points.length; i++) {\n const prev = points[i - 1];\n const curr = points[i];\n if (prev.out && curr.in) {\n // Approximate bezier with chord * 1.2\n length += dist(prev.x, prev.y, curr.x, curr.y) * 1.2;\n } else {\n length += dist(prev.x, prev.y, curr.x, curr.y);\n }\n }\n if (closed && points.length > 1) {\n const first = points[0];\n const last = points[points.length - 1];\n length += dist(last.x, last.y, first.x, first.y);\n }\n return length;\n}\n\n// ── Renderers ───────────────────────────────────────────────\n\nfunction renderRect(\n ctx: RenderContext,\n width: number,\n height: number,\n cornerRadius: number | [number, number, number, number] | undefined,\n visual: ShapeVisual,\n): void {\n if (visual.fill) {\n applyFill(ctx, visual.fill, width, height);\n if (cornerRadius && ctx.roundRect) {\n ctx.beginPath();\n ctx.roundRect(0, 0, width, height, cornerRadius);\n ctx.fill();\n } else {\n ctx.fillRect(0, 0, width, height);\n }\n }\n if (visual.stroke) {\n const perimeter = rectPerimeter(width, height);\n applyStroke(ctx, visual.stroke, perimeter);\n if (cornerRadius && ctx.roundRect) {\n ctx.beginPath();\n ctx.roundRect(0, 0, width, height, cornerRadius);\n ctx.stroke();\n } else {\n ctx.strokeRect(0, 0, width, height);\n }\n }\n}\n\nfunction renderEllipse(\n ctx: RenderContext,\n width: number,\n height: number,\n visual: ShapeVisual,\n): void {\n ctx.beginPath();\n ctx.ellipse(width / 2, height / 2, width / 2, height / 2, 0, 0, Math.PI * 2);\n\n if (visual.fill) {\n applyFill(ctx, visual.fill, width, height);\n ctx.fill();\n }\n if (visual.stroke) {\n const perimeter = ellipsePerimeter(width, height);\n applyStroke(ctx, visual.stroke, perimeter);\n ctx.stroke();\n }\n}\n\nfunction renderPath(\n ctx: RenderContext,\n points: { x: number; y: number; in?: { x: number; y: number }; out?: { x: number; y: number } }[],\n closed: boolean | undefined,\n visual: ShapeVisual,\n): void {\n if (points.length < 2) return;\n\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n\n for (let i = 1; i < points.length; i++) {\n const prev = points[i - 1];\n const curr = points[i];\n\n if (prev.out && curr.in) {\n ctx.bezierCurveTo(\n prev.x + prev.out.x, prev.y + prev.out.y,\n curr.x + curr.in.x, curr.y + curr.in.y,\n curr.x, curr.y,\n );\n } else {\n ctx.lineTo(curr.x, curr.y);\n }\n }\n\n if (closed) ctx.closePath();\n\n if (visual.fill) {\n applyFill(ctx, visual.fill, 0, 0);\n ctx.fill();\n }\n if (visual.stroke) {\n const perimeter = pathPerimeter(points, closed);\n applyStroke(ctx, visual.stroke, perimeter);\n ctx.stroke();\n }\n}\n","import type { TextVisual } from \"@a-company/atelier-types\";\nimport type { RenderContext } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\nimport { colorToCSS } from \"../styles.js\";\n\nexport function renderText(ctx: RenderContext, eff: EffectiveLayer): void {\n const visual = eff.visual as TextVisual;\n const { style } = visual;\n\n // Build font string\n const fontStyle = style.fontStyle ?? \"normal\";\n const fontWeight = style.fontWeight ?? \"normal\";\n const fontSize = style.fontSize;\n const fontFamily = style.fontFamily;\n ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;\n\n // Set alignment — position text within its bounding box\n const align = style.textAlign ?? \"left\";\n ctx.textAlign = align;\n ctx.textBaseline = \"top\";\n\n // Set color\n ctx.fillStyle = colorToCSS(style.color);\n\n // Canvas 2D textAlign anchors at the draw point, so offset within bounds:\n // \"left\" → draw at x=0 (text flows right from left edge)\n // \"center\" → draw at x=width/2 (text centers within bounds)\n // \"right\" → draw at x=width (text flows left from right edge)\n let textX = 0;\n if (align === \"center\") {\n textX = eff.width / 2;\n } else if (align === \"right\") {\n textX = eff.width;\n }\n\n ctx.fillText(visual.content, textX, 0);\n}\n","import type { ImageVisual } from \"@a-company/atelier-types\";\nimport type { RenderContext } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\nimport type { ImageCache } from \"../image-cache.js\";\n\n/**\n * Render an image layer to the canvas.\n * Supports sourceRect cropping and spritesheet grid animation.\n * If the image hasn't loaded yet, triggers a cache load and returns\n * (the image will appear on the next re-render).\n */\nexport function renderImage(ctx: RenderContext, eff: EffectiveLayer, imageCache: ImageCache): void {\n const visual = eff.visual as ImageVisual;\n const src = visual.src;\n if (!src) return;\n\n const img = imageCache.get(src);\n if (!img) {\n imageCache.load(src);\n return;\n }\n\n // Spritesheet grid computation takes precedence over manual sourceRect\n if (visual.spritesheet) {\n const { columns, rows, frameWidth, frameHeight, frameCount } = visual.spritesheet;\n const maxFrames = frameCount ?? (columns * rows);\n const idx = Math.max(0, Math.min(Math.floor(visual.frameIndex ?? 0), maxFrames - 1));\n const col = idx % columns;\n const row = Math.floor(idx / columns);\n const sx = col * frameWidth;\n const sy = row * frameHeight;\n (ctx.drawImage as Function)(img, sx, sy, frameWidth, frameHeight, 0, 0, eff.width, eff.height);\n return;\n }\n\n // Manual sourceRect crop\n if (visual.sourceRect) {\n const sr = visual.sourceRect;\n (ctx.drawImage as Function)(img, sr.x, sr.y, sr.width, sr.height, 0, 0, eff.width, eff.height);\n return;\n }\n\n // Default: draw full image to bounds\n ctx.drawImage(img, 0, 0, eff.width, eff.height);\n}\n","import type { VideoVisual } from \"@a-company/atelier-types\";\nimport type { RenderContext, VideoFrameProvider } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\n\n/**\n * Render a video layer to the canvas at the given source time.\n * Delegates actual frame extraction to the injected VideoFrameProvider,\n * which may be backed by HTMLVideoElement (preview) or WebCodecs (export).\n * Returns without drawing if the provider returns null — caller retries next tick.\n */\nexport function renderVideo(\n ctx: RenderContext,\n eff: EffectiveLayer,\n sourceTime: number,\n provider: VideoFrameProvider,\n): void {\n const visual = eff.visual as VideoVisual;\n const src = visual.src;\n if (!src) return;\n\n const frame = provider(src, sourceTime, eff.width, eff.height);\n if (!frame) return;\n\n ctx.drawImage(frame as unknown, 0, 0, eff.width, eff.height);\n}\n","import type { AtelierDocument, RefVisual, ImageVisual } from \"@a-company/atelier-types\";\nimport { resolveFrame } from \"@a-company/atelier-core\";\nimport type { RenderContext, DocumentResolver } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\nimport { buildEffectiveLayer } from \"../apply-properties.js\";\nimport { renderShape } from \"./shape-renderer.js\";\nimport { renderText } from \"./text-renderer.js\";\nimport { renderImage } from \"./image-renderer.js\";\nimport type { ImageCache } from \"../image-cache.js\";\n\nexport interface RefRenderOpts {\n documentResolver?: DocumentResolver;\n maxRefDepth?: number;\n imageCache?: ImageCache;\n /** Internal: tracks visited refs for cycle detection */\n _visitedRefs?: Set<string>;\n /** Internal: current recursion depth */\n _depth?: number;\n}\n\n/**\n * Render a ref layer. If a documentResolver is provided, resolves and renders\n * the sub-document inline. Otherwise falls back to a placeholder rectangle.\n */\nexport function renderRef(\n ctx: RenderContext,\n eff: EffectiveLayer,\n opts?: RefRenderOpts,\n _parentDoc?: AtelierDocument,\n): void {\n const visual = eff.visual as RefVisual;\n const resolver = opts?.documentResolver;\n\n if (!resolver) {\n renderPlaceholder(ctx, eff, `REF: ${visual.src}`);\n return;\n }\n\n const depth = opts?._depth ?? 0;\n const maxDepth = opts?.maxRefDepth ?? 4;\n\n if (depth >= maxDepth) {\n renderPlaceholder(ctx, eff, \"MAX DEPTH\");\n return;\n }\n\n const visitedRefs = opts?._visitedRefs ?? new Set<string>();\n\n if (visitedRefs.has(visual.src)) {\n renderPlaceholder(ctx, eff, \"CYCLE\");\n return;\n }\n\n const subDoc = resolver(visual.src);\n if (!subDoc) {\n renderPlaceholder(ctx, eff, \"NOT FOUND\");\n return;\n }\n\n // Determine which state and frame to render\n const stateNames = Object.keys(subDoc.states);\n if (stateNames.length === 0) {\n renderPlaceholder(ctx, eff, \"NO STATES\");\n return;\n }\n\n const stateName = visual.state ?? stateNames[0];\n const stateObj = subDoc.states[stateName];\n if (!stateObj) {\n renderPlaceholder(ctx, eff, `STATE? ${stateName}`);\n return;\n }\n\n const maxFrame = Math.max(0, stateObj.duration - 1);\n const frame = Math.min(visual.frame ?? 0, maxFrame);\n\n // Resolve the sub-document frame\n const resolved = resolveFrame(subDoc, stateName, frame);\n\n // Mark as visited for cycle detection\n visitedRefs.add(visual.src);\n\n // Scale to fit eff bounds\n const scaleX = eff.width / subDoc.canvas.width;\n const scaleY = eff.height / subDoc.canvas.height;\n\n ctx.save();\n ctx.scale(scaleX, scaleY);\n\n // Build and render sub-doc layers\n const { width: subW, height: subH } = subDoc.canvas;\n\n for (const resolvedLayer of resolved.layers) {\n const subEff = buildEffectiveLayer(resolvedLayer, subW, subH);\n\n if (!subEff.visible) continue;\n if (subEff.opacity <= 0) continue;\n\n // Resolve asset for images\n if (resolvedLayer.layer.visual.type === \"image\") {\n const iv = subEff.visual as ImageVisual;\n if (!iv.src && iv.assetId && subDoc.assets?.[iv.assetId]) {\n iv.src = subDoc.assets[iv.assetId].src;\n }\n }\n\n ctx.save();\n ctx.globalAlpha = subEff.opacity;\n ctx.translate(subEff.x, subEff.y);\n\n switch (resolvedLayer.layer.visual.type) {\n case \"shape\":\n renderShape(ctx, subEff);\n break;\n case \"text\":\n renderText(ctx, subEff);\n break;\n case \"image\":\n if (opts?.imageCache) renderImage(ctx, subEff, opts.imageCache);\n break;\n case \"ref\":\n renderRef(ctx, subEff, {\n ...opts,\n _visitedRefs: visitedRefs,\n _depth: depth + 1,\n }, subDoc);\n break;\n case \"group\":\n break;\n }\n\n ctx.restore();\n }\n\n ctx.restore();\n\n // Remove from visited after rendering (allow same ref in different branches)\n visitedRefs.delete(visual.src);\n}\n\n/** Render a dashed placeholder rectangle with label */\nfunction renderPlaceholder(ctx: RenderContext, eff: EffectiveLayer, label: string): void {\n const { width, height } = eff;\n\n ctx.strokeStyle = \"#888888\";\n ctx.lineWidth = 2;\n ctx.setLineDash([6, 4]);\n ctx.strokeRect(0, 0, width, height);\n ctx.setLineDash([]);\n\n ctx.fillStyle = \"#888888\";\n ctx.font = `${Math.max(12, Math.min(16, height * 0.15))}px sans-serif`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n ctx.fillText(label, width / 2, height / 2, width - 8);\n}\n","import type { AtelierDocument, ImageVisual, VideoVisual, Shape } from \"@a-company/atelier-types\";\nimport type { ResolvedFrame } from \"@a-company/atelier-core\";\nimport type { RenderContext, DocumentResolver, VideoFrameProvider } from \"./canvas-types.js\";\nimport { buildEffectiveLayer, type EffectiveLayer } from \"./apply-properties.js\";\nimport { renderShape } from \"./renderers/shape-renderer.js\";\nimport { renderText } from \"./renderers/text-renderer.js\";\nimport { renderImage } from \"./renderers/image-renderer.js\";\nimport { renderVideo } from \"./renderers/video-renderer.js\";\nimport { renderRef } from \"./renderers/ref-renderer.js\";\nimport type { ImageCache } from \"./image-cache.js\";\n\n/** Options for renderFrame */\nexport interface RenderOptions {\n imageCache?: ImageCache;\n documentResolver?: DocumentResolver;\n maxRefDepth?: number;\n videoFrameProvider?: VideoFrameProvider;\n}\n\n/**\n * Render a resolved frame to a Canvas 2D context.\n * Clears the canvas and draws all visible layers in order.\n */\nexport function renderFrame(\n ctx: RenderContext,\n resolvedFrame: ResolvedFrame,\n doc: AtelierDocument,\n optsOrCache?: RenderOptions | ImageCache,\n): void {\n // Backward compatible: detect old ImageCache arg vs new RenderOptions\n let imageCache: ImageCache | undefined;\n let documentResolver: DocumentResolver | undefined;\n let videoFrameProvider: VideoFrameProvider | undefined;\n let maxRefDepth = 4;\n\n if (optsOrCache && typeof (optsOrCache as ImageCache).get === \"function\") {\n imageCache = optsOrCache as ImageCache;\n } else if (optsOrCache) {\n const opts = optsOrCache as RenderOptions;\n imageCache = opts.imageCache;\n documentResolver = opts.documentResolver;\n videoFrameProvider = opts.videoFrameProvider;\n maxRefDepth = opts.maxRefDepth ?? 4;\n }\n const { width, height } = doc.canvas;\n\n // Clear canvas\n ctx.fillStyle = doc.canvas.background ?? \"transparent\";\n ctx.fillRect(0, 0, width, height);\n\n // Build effective layers into a map for ancestor transform lookups\n const effMap = new Map<string, EffectiveLayer>();\n const effList: EffectiveLayer[] = [];\n const videoSourceTimeMap = new Map<string, number>();\n\n for (const resolvedLayer of resolvedFrame.layers) {\n const eff = buildEffectiveLayer(resolvedLayer, width, height);\n effMap.set(resolvedLayer.layer.id, eff);\n effList.push(eff);\n if (resolvedLayer.videoSourceTime !== undefined) {\n videoSourceTimeMap.set(resolvedLayer.layer.id, resolvedLayer.videoSourceTime);\n }\n }\n\n // Render each layer in order (painters algorithm — first = back)\n for (const eff of effList) {\n const { layer } = eff;\n\n // Skip invisible layers\n if (!eff.visible) continue;\n\n // Skip fully transparent layers\n if (eff.opacity <= 0) continue;\n\n // Resolve assetId → src for image visuals\n if (layer.visual.type === \"image\") {\n const iv = eff.visual as ImageVisual;\n if (!iv.src && iv.assetId && doc.assets?.[iv.assetId]) {\n iv.src = doc.assets[iv.assetId].src;\n }\n }\n\n // Resolve assetId → src for video visuals\n if (layer.visual.type === \"video\") {\n const vv = eff.visual as VideoVisual;\n if (!vv.src && vv.assetId && doc.assets?.[vv.assetId]) {\n vv.src = doc.assets[vv.assetId].src;\n }\n }\n\n ctx.save();\n\n // Apply ancestor transforms (group/parent inheritance)\n applyAncestorTransforms(ctx, layer.id, effMap, doc);\n\n // Apply transforms\n ctx.globalAlpha = eff.opacity;\n\n // Apply blend mode\n if (eff.blendMode !== \"normal\") {\n ctx.globalCompositeOperation = blendModeToComposite(eff.blendMode);\n }\n\n ctx.translate(eff.x, eff.y);\n\n // Apply anchor-relative transforms\n const anchorPixelX = eff.anchorX * eff.width;\n const anchorPixelY = eff.anchorY * eff.height;\n\n // Combine explicit rotation with motion path auto-rotation\n const totalRotation = eff.rotation + eff.motionPathAngle;\n\n if (totalRotation !== 0 || eff.scaleX !== 1 || eff.scaleY !== 1) {\n ctx.translate(anchorPixelX, anchorPixelY);\n if (totalRotation !== 0) {\n ctx.rotate((totalRotation * Math.PI) / 180);\n }\n if (eff.scaleX !== 1 || eff.scaleY !== 1) {\n ctx.scale(eff.scaleX, eff.scaleY);\n }\n ctx.translate(-anchorPixelX, -anchorPixelY);\n }\n\n // Apply shadow if present\n if (eff.shadow) {\n ctx.shadowColor = eff.shadow.color;\n ctx.shadowBlur = eff.shadow.blur;\n ctx.shadowOffsetX = eff.shadow.offsetX;\n ctx.shadowOffsetY = eff.shadow.offsetY;\n }\n\n // Apply clip path if present\n if (layer.clipPath) {\n applyClipPath(ctx, layer.clipPath, eff.width, eff.height);\n }\n\n // Tint requires offscreen compositing — draw to offscreen if tint is active\n const hasTint = eff.tint && eff.tint.amount > 0 && ctx.createOffscreen;\n let renderCtx = ctx;\n let offscreen: { ctx: RenderContext; canvas: unknown } | null = null;\n\n if (hasTint) {\n offscreen = ctx.createOffscreen!(eff.width, eff.height);\n renderCtx = offscreen.ctx;\n }\n\n // Ref rendering options (passed through for sub-doc composition)\n const refOpts = { documentResolver, maxRefDepth, imageCache };\n\n // Dispatch to type-specific renderer\n switch (layer.visual.type) {\n case \"shape\":\n renderShape(renderCtx, eff);\n break;\n case \"text\":\n renderText(renderCtx, eff);\n break;\n case \"image\":\n if (imageCache) renderImage(renderCtx, eff, imageCache);\n break;\n case \"video\":\n if (videoFrameProvider) {\n renderVideo(renderCtx, eff, videoSourceTimeMap.get(layer.id) ?? 0, videoFrameProvider);\n }\n break;\n case \"group\":\n // Groups are structural containers — no visual output\n break;\n case \"ref\":\n renderRef(renderCtx, eff, refOpts, doc);\n break;\n }\n\n // Apply tint via multiply composite on offscreen canvas\n if (hasTint && offscreen && eff.tint) {\n const offCtx = offscreen.ctx;\n // Draw tint color over the content using multiply\n offCtx.save();\n offCtx.globalCompositeOperation = \"multiply\";\n offCtx.fillStyle = eff.tint.color;\n offCtx.fillRect(0, 0, eff.width, eff.height);\n offCtx.restore();\n\n // Clip to original content shape using destination-in\n offCtx.save();\n offCtx.globalCompositeOperation = \"destination-in\";\n // Re-render the content to create the alpha mask\n switch (layer.visual.type) {\n case \"shape\": renderShape(offCtx, eff); break;\n case \"text\": renderText(offCtx, eff); break;\n case \"image\": if (imageCache) renderImage(offCtx, eff, imageCache); break;\n case \"video\": if (videoFrameProvider) renderVideo(offCtx, eff, videoSourceTimeMap.get(layer.id) ?? 0, videoFrameProvider); break;\n case \"ref\": renderRef(offCtx, eff, refOpts, doc); break;\n }\n offCtx.restore();\n\n // Blend tinted offscreen back with original at tint.amount alpha\n // First draw original content\n switch (layer.visual.type) {\n case \"shape\": renderShape(ctx, eff); break;\n case \"text\": renderText(ctx, eff); break;\n case \"image\": if (imageCache) renderImage(ctx, eff, imageCache); break;\n case \"video\": if (videoFrameProvider) renderVideo(ctx, eff, videoSourceTimeMap.get(layer.id) ?? 0, videoFrameProvider); break;\n case \"ref\": renderRef(ctx, eff, refOpts, doc); break;\n }\n // Then overlay tinted version at tint amount\n const prevAlpha = ctx.globalAlpha;\n ctx.globalAlpha = eff.tint.amount;\n ctx.drawImage(offscreen.canvas, 0, 0, eff.width, eff.height);\n ctx.globalAlpha = prevAlpha;\n }\n\n ctx.restore();\n }\n}\n\n/** Apply a shape as a clipping region */\nfunction applyClipPath(ctx: RenderContext, shape: Shape, width: number, height: number): void {\n ctx.beginPath();\n switch (shape.type) {\n case \"rect\":\n if (shape.cornerRadius && ctx.roundRect) {\n ctx.roundRect(0, 0, width, height, shape.cornerRadius);\n } else {\n // Manual rect path for clipping (fillRect doesn't create a path)\n ctx.moveTo(0, 0);\n ctx.lineTo(width, 0);\n ctx.lineTo(width, height);\n ctx.lineTo(0, height);\n ctx.closePath();\n }\n break;\n case \"ellipse\":\n ctx.ellipse(width / 2, height / 2, width / 2, height / 2, 0, 0, Math.PI * 2);\n break;\n case \"path\":\n if (shape.points.length >= 2) {\n ctx.moveTo(shape.points[0].x, shape.points[0].y);\n for (let i = 1; i < shape.points.length; i++) {\n const prev = shape.points[i - 1];\n const curr = shape.points[i];\n if (prev.out && curr.in) {\n ctx.bezierCurveTo(\n prev.x + prev.out.x, prev.y + prev.out.y,\n curr.x + curr.in.x, curr.y + curr.in.y,\n curr.x, curr.y,\n );\n } else {\n ctx.lineTo(curr.x, curr.y);\n }\n }\n if (shape.closed) ctx.closePath();\n }\n break;\n }\n ctx.clip();\n}\n\n/** Map Atelier blend mode names to Canvas 2D globalCompositeOperation values */\nfunction blendModeToComposite(mode: string): string {\n const map: Record<string, string> = {\n \"multiply\": \"multiply\",\n \"screen\": \"screen\",\n \"overlay\": \"overlay\",\n \"darken\": \"darken\",\n \"lighten\": \"lighten\",\n \"color-dodge\": \"color-dodge\",\n \"color-burn\": \"color-burn\",\n \"hard-light\": \"hard-light\",\n \"soft-light\": \"soft-light\",\n \"difference\": \"difference\",\n \"exclusion\": \"exclusion\",\n \"hue\": \"hue\",\n \"saturation\": \"saturation\",\n \"color\": \"color\",\n \"luminosity\": \"luminosity\",\n };\n return map[mode] ?? \"source-over\";\n}\n\n/**\n * Walk the parentId chain and apply each ancestor's transforms.\n * This makes child layers inherit parent position/rotation/scale.\n */\nfunction applyAncestorTransforms(\n ctx: RenderContext,\n layerId: string,\n effMap: Map<string, EffectiveLayer>,\n doc: AtelierDocument,\n): void {\n // Collect ancestor chain (excluding self)\n const chain: EffectiveLayer[] = [];\n const layer = doc.layers.find((l) => l.id === layerId);\n let parentId = layer?.parentId;\n const visited = new Set<string>();\n\n while (parentId && !visited.has(parentId)) {\n visited.add(parentId);\n const parentEff = effMap.get(parentId);\n if (!parentEff) break;\n chain.push(parentEff);\n parentId = parentEff.layer.parentId;\n }\n\n // Apply from root ancestor down to direct parent\n for (let i = chain.length - 1; i >= 0; i--) {\n const p = chain[i];\n ctx.translate(p.x, p.y);\n\n const ax = p.anchorX * p.width;\n const ay = p.anchorY * p.height;\n\n if (p.rotation !== 0 || p.scaleX !== 1 || p.scaleY !== 1) {\n ctx.translate(ax, ay);\n if (p.rotation !== 0) ctx.rotate((p.rotation * Math.PI) / 180);\n if (p.scaleX !== 1 || p.scaleY !== 1) ctx.scale(p.scaleX, p.scaleY);\n ctx.translate(-ax, -ay);\n }\n }\n}\n","/**\n * A loaded image entry that can be drawn via RenderContext.drawImage.\n */\nexport interface CachedImage {\n complete: boolean;\n image: unknown;\n}\n\n/**\n * Simple image cache for loading and caching images.\n * Browser-agnostic — the actual Image constructor is injected via createImage.\n * Triggers an onLoad callback when an image finishes loading so the\n * renderer can re-render the current frame.\n */\nexport class ImageCache {\n private cache = new Map<string, CachedImage>();\n private loading = new Set<string>();\n private onLoad?: () => void;\n private createImage?: (src: string, onLoad: () => void, onError: () => void) => unknown;\n\n constructor(opts?: {\n onLoad?: () => void;\n createImage?: (src: string, onLoad: () => void, onError: () => void) => unknown;\n }) {\n this.onLoad = opts?.onLoad;\n this.createImage = opts?.createImage;\n }\n\n get(src: string): unknown | null {\n const entry = this.cache.get(src);\n return entry?.complete ? entry.image : null;\n }\n\n load(src: string): void {\n if (this.cache.has(src) || this.loading.has(src)) return;\n if (!this.createImage) return;\n this.loading.add(src);\n const image = this.createImage(\n src,\n () => {\n this.cache.set(src, { complete: true, image });\n this.loading.delete(src);\n this.onLoad?.();\n },\n () => {\n this.loading.delete(src);\n },\n );\n }\n}\n","import type { AtelierDocument, ImageVisual, RefVisual } from \"@a-company/atelier-types\";\nimport { resolveFrame, type ResolvedFrame } from \"@a-company/atelier-core\";\nimport { buildEffectiveLayer, type EffectiveLayer, type DocumentResolver } from \"@a-company/atelier-canvas\";\nimport { buildTransform, buildStyleAttrs } from \"./svg-properties.js\";\nimport { renderShapeSVG } from \"./svg-shapes.js\";\nimport { renderTextSVG } from \"./svg-text.js\";\nimport { buildShadowFilter, buildTintFilter, resetFilterCounter } from \"./svg-filters.js\";\nimport { resetGradientCounter } from \"./svg-gradients.js\";\nimport { buildClipPathDef, resetClipCounter } from \"./svg-clip.js\";\nimport { escapeXml } from \"./svg-properties.js\";\n\nexport interface RenderSVGOptions {\n /** Include XML declaration (default: false) */\n xmlDeclaration?: boolean;\n /** Include viewBox attribute (default: true) */\n viewBox?: boolean;\n /** Indent size in spaces (default: 2) */\n indent?: number;\n /** Resolves ref layer src paths to loaded AtelierDocuments */\n documentResolver?: DocumentResolver;\n /** Maximum ref nesting depth (default: 4) */\n maxRefDepth?: number;\n}\n\n/**\n * Render a resolved frame as an SVG string.\n * If no resolved frame is provided, resolves the given state and frame.\n */\nexport function renderFrameSVG(\n doc: AtelierDocument,\n stateOrFrame: string | ResolvedFrame,\n frame?: number,\n opts?: RenderSVGOptions,\n): string {\n // Reset counters for deterministic IDs\n resetGradientCounter();\n resetFilterCounter();\n resetClipCounter();\n\n let resolved: ResolvedFrame;\n if (typeof stateOrFrame === \"string\") {\n resolved = resolveFrame(doc, stateOrFrame, frame ?? 0);\n } else {\n resolved = stateOrFrame;\n }\n\n const { width, height } = doc.canvas;\n const indent = opts?.indent ?? 2;\n const pad = \" \".repeat(indent);\n\n // Build effective layers\n const effLayers: EffectiveLayer[] = resolved.layers.map(rl =>\n buildEffectiveLayer(rl, width, height),\n );\n\n // Collect all defs and layer elements\n const allDefs: string[] = [];\n const layerElements: string[] = [];\n\n for (let i = 0; i < effLayers.length; i++) {\n const eff = effLayers[i];\n const layer = resolved.layers[i].layer;\n\n // Skip invisible or fully transparent\n if (!eff.visible) continue;\n if (eff.opacity <= 0) continue;\n\n // Resolve asset for images\n if (layer.visual.type === \"image\") {\n const iv = eff.visual as ImageVisual;\n if (!iv.src && iv.assetId && doc.assets?.[iv.assetId]) {\n (eff.visual as ImageVisual).src = doc.assets[iv.assetId].src;\n }\n }\n\n // Build transform\n const transform = buildTransform(eff);\n const styleAttrs = buildStyleAttrs(eff);\n\n // Build shadow filter\n const filterResult = buildShadowFilter(eff);\n if (filterResult) allDefs.push(filterResult.defs);\n\n // Build tint filter\n const tintResult = buildTintFilter(eff);\n if (tintResult) allDefs.push(tintResult.defs);\n\n // Build clip path\n let clipAttr = \"\";\n if (layer.clipPath) {\n const clipResult = buildClipPathDef(layer.clipPath, eff.width, eff.height);\n if (clipResult.defs) {\n allDefs.push(clipResult.defs);\n clipAttr = ` clip-path=\"${clipResult.clipRef}\"`;\n }\n }\n\n // Build group attributes\n const gAttrs: string[] = [];\n if (transform) gAttrs.push(`transform=\"${transform}\"`);\n if (styleAttrs) gAttrs.push(styleAttrs);\n // Apply combined or individual filters\n if (filterResult && tintResult) {\n // When both shadow and tint exist, we need a combined filter\n // For simplicity, apply shadow filter and tint separately via style\n gAttrs.push(`filter=\"${filterResult.filterRef}\"`);\n // Tint is a second filter — wrap content in nested group\n } else if (filterResult) {\n gAttrs.push(`filter=\"${filterResult.filterRef}\"`);\n } else if (tintResult) {\n gAttrs.push(`filter=\"${tintResult.filterRef}\"`);\n }\n if (clipAttr) gAttrs.push(clipAttr.trim());\n\n // Render visual content\n let content = \"\";\n let layerDefs = \"\";\n\n switch (layer.visual.type) {\n case \"shape\": {\n const result = renderShapeSVG(eff, eff.visual as import(\"@a-company/atelier-types\").ShapeVisual);\n content = result.elements;\n layerDefs = result.defs;\n break;\n }\n case \"text\":\n content = renderTextSVG(eff, eff.visual as import(\"@a-company/atelier-types\").TextVisual);\n break;\n case \"image\": {\n const iv = eff.visual as ImageVisual;\n if (iv.src) {\n if (iv.spritesheet) {\n // Spritesheet: compute source rect and use full sheet dimensions for inner image\n const { columns, rows, frameWidth, frameHeight, frameCount } = iv.spritesheet;\n const maxFrames = frameCount ?? (columns * rows);\n const idx = Math.max(0, Math.min(Math.floor(iv.frameIndex ?? 0), maxFrames - 1));\n const col = idx % columns;\n const row = Math.floor(idx / columns);\n const sx = col * frameWidth;\n const sy = row * frameHeight;\n const imgW = columns * frameWidth;\n const imgH = rows * frameHeight;\n content = `<svg viewBox=\"${sx} ${sy} ${frameWidth} ${frameHeight}\" width=\"${eff.width}\" height=\"${eff.height}\">` +\n `<image href=\"${escapeXml(iv.src)}\" width=\"${imgW}\" height=\"${imgH}\" />` +\n `</svg>`;\n } else if (iv.sourceRect) {\n // Manual sourceRect: viewBox crops from image coordinate space\n const sr = iv.sourceRect;\n content = `<svg viewBox=\"${sr.x} ${sr.y} ${sr.width} ${sr.height}\" width=\"${eff.width}\" height=\"${eff.height}\">` +\n `<image href=\"${escapeXml(iv.src)}\" width=\"${eff.width}\" height=\"${eff.height}\" />` +\n `</svg>`;\n } else {\n content = `<image href=\"${escapeXml(iv.src)}\" width=\"${eff.width}\" height=\"${eff.height}\" />`;\n }\n }\n break;\n }\n case \"group\":\n // Groups are structural — no visual content in SVG either\n break;\n case \"ref\": {\n const refVisual = eff.visual as RefVisual;\n const refContent = renderRefSVG(eff, refVisual, doc, opts);\n content = refContent;\n break;\n }\n }\n\n if (layerDefs) allDefs.push(layerDefs);\n\n if (content) {\n const gOpen = gAttrs.length > 0 ? `<g ${gAttrs.join(\" \")}>` : \"<g>\";\n layerElements.push(`${pad}${gOpen}${content}</g>`);\n }\n }\n\n // Build SVG\n const lines: string[] = [];\n\n if (opts?.xmlDeclaration) {\n lines.push('<?xml version=\"1.0\" encoding=\"UTF-8\"?>');\n }\n\n const viewBox = opts?.viewBox !== false ? ` viewBox=\"0 0 ${width} ${height}\"` : \"\";\n const bg = doc.canvas.background;\n\n lines.push(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\"${viewBox}>`);\n\n // Defs section\n if (allDefs.length > 0) {\n lines.push(`${pad}<defs>`);\n for (const def of allDefs) {\n lines.push(`${pad}${pad}${def}`);\n }\n lines.push(`${pad}</defs>`);\n }\n\n // Background\n if (bg && bg !== \"transparent\") {\n lines.push(`${pad}<rect width=\"${width}\" height=\"${height}\" fill=\"${bg}\" />`);\n }\n\n // Layers\n lines.push(...layerElements);\n\n lines.push(\"</svg>\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render a ref layer as SVG. Uses documentResolver to inline sub-doc content,\n * or falls back to a dashed placeholder rectangle.\n */\nfunction renderRefSVG(\n eff: EffectiveLayer,\n visual: RefVisual,\n _parentDoc: AtelierDocument,\n opts?: RenderSVGOptions,\n _depth?: number,\n _visitedRefs?: Set<string>,\n): string {\n const resolver = opts?.documentResolver;\n\n if (!resolver) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" />`;\n }\n\n const depth = _depth ?? 0;\n const maxDepth = opts?.maxRefDepth ?? 4;\n if (depth >= maxDepth) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#c33\" stroke-dasharray=\"4 2\" /><text x=\"${eff.width / 2}\" y=\"${eff.height / 2}\" text-anchor=\"middle\" dominant-baseline=\"middle\" fill=\"#c33\" font-size=\"12\">MAX DEPTH</text>`;\n }\n\n const visitedRefs = _visitedRefs ?? new Set<string>();\n if (visitedRefs.has(visual.src)) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#c33\" stroke-dasharray=\"4 2\" /><text x=\"${eff.width / 2}\" y=\"${eff.height / 2}\" text-anchor=\"middle\" dominant-baseline=\"middle\" fill=\"#c33\" font-size=\"12\">CYCLE</text>`;\n }\n\n const subDoc = resolver(visual.src);\n if (!subDoc) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" /><text x=\"${eff.width / 2}\" y=\"${eff.height / 2}\" text-anchor=\"middle\" dominant-baseline=\"middle\" fill=\"#999\" font-size=\"12\">NOT FOUND</text>`;\n }\n\n const stateNames = Object.keys(subDoc.states);\n if (stateNames.length === 0) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" />`;\n }\n\n const stateName = visual.state ?? stateNames[0];\n const stateObj = subDoc.states[stateName];\n if (!stateObj) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" />`;\n }\n\n const maxFrame = Math.max(0, stateObj.duration - 1);\n const frame = Math.min(visual.frame ?? 0, maxFrame);\n\n visitedRefs.add(visual.src);\n\n // Render sub-doc as nested <svg> with viewBox for scaling\n const subW = subDoc.canvas.width;\n const subH = subDoc.canvas.height;\n const resolved = resolveFrame(subDoc, stateName, frame);\n\n const subParts: string[] = [];\n for (const rl of resolved.layers) {\n const subEff = buildEffectiveLayer(rl, subW, subH);\n if (!subEff.visible || subEff.opacity <= 0) continue;\n\n // Resolve asset\n if (rl.layer.visual.type === \"image\") {\n const iv = subEff.visual as ImageVisual;\n if (!iv.src && iv.assetId && subDoc.assets?.[iv.assetId]) {\n iv.src = subDoc.assets[iv.assetId].src;\n }\n }\n\n const transform = buildTransform(subEff);\n const styleAttrs = buildStyleAttrs(subEff);\n const gAttrs: string[] = [];\n if (transform) gAttrs.push(`transform=\"${transform}\"`);\n if (styleAttrs) gAttrs.push(styleAttrs);\n\n let childContent = \"\";\n switch (rl.layer.visual.type) {\n case \"shape\": {\n const result = renderShapeSVG(subEff, subEff.visual as import(\"@a-company/atelier-types\").ShapeVisual);\n childContent = result.elements;\n break;\n }\n case \"text\":\n childContent = renderTextSVG(subEff, subEff.visual as import(\"@a-company/atelier-types\").TextVisual);\n break;\n case \"image\": {\n const iv = subEff.visual as ImageVisual;\n if (iv.src) {\n childContent = `<image href=\"${escapeXml(iv.src)}\" width=\"${subEff.width}\" height=\"${subEff.height}\" />`;\n }\n break;\n }\n case \"ref\": {\n const refV = subEff.visual as RefVisual;\n childContent = renderRefSVG(subEff, refV, subDoc, opts, depth + 1, visitedRefs);\n break;\n }\n }\n\n if (childContent) {\n const gOpen = gAttrs.length > 0 ? `<g ${gAttrs.join(\" \")}>` : \"<g>\";\n subParts.push(`${gOpen}${childContent}</g>`);\n }\n }\n\n visitedRefs.delete(visual.src);\n\n return `<svg x=\"0\" y=\"0\" width=\"${eff.width}\" height=\"${eff.height}\" viewBox=\"0 0 ${subW} ${subH}\">${subParts.join(\"\")}</svg>`;\n}\n","import type { EffectiveLayer } from \"@a-company/atelier-canvas\";\n\n/** Build SVG transform attribute from effective layer values */\nexport function buildTransform(eff: EffectiveLayer): string {\n const parts: string[] = [];\n\n // Translate to position\n if (eff.x !== 0 || eff.y !== 0) {\n parts.push(`translate(${eff.x}, ${eff.y})`);\n }\n\n const totalRotation = eff.rotation + eff.motionPathAngle;\n if (totalRotation !== 0 || eff.scaleX !== 1 || eff.scaleY !== 1) {\n const ax = eff.anchorX * eff.width;\n const ay = eff.anchorY * eff.height;\n\n // Move to anchor, apply rotation/scale, move back\n if (ax !== 0 || ay !== 0) {\n parts.push(`translate(${ax}, ${ay})`);\n }\n if (totalRotation !== 0) {\n parts.push(`rotate(${totalRotation})`);\n }\n if (eff.scaleX !== 1 || eff.scaleY !== 1) {\n parts.push(`scale(${eff.scaleX}, ${eff.scaleY})`);\n }\n if (ax !== 0 || ay !== 0) {\n parts.push(`translate(${-ax}, ${-ay})`);\n }\n }\n\n return parts.length > 0 ? parts.join(\" \") : \"\";\n}\n\n/** Build common SVG style attributes */\nexport function buildStyleAttrs(eff: EffectiveLayer): string {\n const attrs: string[] = [];\n\n if (eff.opacity < 1) {\n attrs.push(`opacity=\"${eff.opacity}\"`);\n }\n\n if (eff.blendMode !== \"normal\") {\n attrs.push(`style=\"mix-blend-mode: ${eff.blendMode}\"`);\n }\n\n return attrs.join(\" \");\n}\n\n/** Escape XML special characters */\nexport function escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n","import type { Fill, LinearGradientFill, RadialGradientFill, Color, RGBAColor, HSLAColor } from \"@a-company/atelier-types\";\n\nlet gradientIdCounter = 0;\n\nexport function resetGradientCounter(): void {\n gradientIdCounter = 0;\n}\n\n/** Convert an Atelier Color to a CSS color string */\nexport function colorToCSS(color: Color): string {\n if (typeof color === \"string\") return color;\n if (\"r\" in color) {\n const c = color as RGBAColor;\n return `rgba(${Math.round(c.r)}, ${Math.round(c.g)}, ${Math.round(c.b)}, ${c.a})`;\n }\n if (\"h\" in color) {\n const c = color as HSLAColor;\n return `hsla(${c.h}, ${c.s}%, ${c.l}%, ${c.a})`;\n }\n return \"#000000\";\n}\n\n/** Generate SVG gradient defs and return the fill reference */\nexport function buildGradientDef(fill: Fill, width: number, height: number): { defs: string; fillRef: string } {\n if (fill.type === \"solid\") {\n return { defs: \"\", fillRef: colorToCSS(fill.color) };\n }\n\n if (fill.type === \"linear-gradient\") {\n return buildLinearGradient(fill, width, height);\n }\n\n if (fill.type === \"radial-gradient\") {\n return buildRadialGradient(fill, width, height);\n }\n\n return { defs: \"\", fillRef: \"none\" };\n}\n\nfunction buildLinearGradient(fill: LinearGradientFill, _width: number, _height: number): { defs: string; fillRef: string } {\n const id = `grad-${++gradientIdCounter}`;\n const rad = (fill.angle * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n\n // Map angle to x1,y1,x2,y2 (0-1 percentages)\n const x1 = 0.5 - cos * 0.5;\n const y1 = 0.5 - sin * 0.5;\n const x2 = 0.5 + cos * 0.5;\n const y2 = 0.5 + sin * 0.5;\n\n const stops = fill.stops.map(s =>\n `<stop offset=\"${s.offset}\" stop-color=\"${colorToCSS(s.color)}\" />`\n ).join(\"\");\n\n const def = `<linearGradient id=\"${id}\" x1=\"${x1}\" y1=\"${y1}\" x2=\"${x2}\" y2=\"${y2}\">${stops}</linearGradient>`;\n return { defs: def, fillRef: `url(#${id})` };\n}\n\nfunction buildRadialGradient(fill: RadialGradientFill, width: number, height: number): { defs: string; fillRef: string } {\n const id = `grad-${++gradientIdCounter}`;\n\n const cx = typeof fill.center.x === \"number\" ? fill.center.x : (parseFloat(fill.center.x) / 100) * width;\n const cy = typeof fill.center.y === \"number\" ? fill.center.y : (parseFloat(fill.center.y) / 100) * height;\n const r = typeof fill.radius === \"number\" ? fill.radius : (parseFloat(fill.radius) / 100) * Math.max(width, height);\n\n const stops = fill.stops.map(s =>\n `<stop offset=\"${s.offset}\" stop-color=\"${colorToCSS(s.color)}\" />`\n ).join(\"\");\n\n const def = `<radialGradient id=\"${id}\" cx=\"${cx}\" cy=\"${cy}\" r=\"${r}\" gradientUnits=\"userSpaceOnUse\">${stops}</radialGradient>`;\n return { defs: def, fillRef: `url(#${id})` };\n}\n","import type { ShapeVisual, Shape, RectShape, PathShape, Stroke } from \"@a-company/atelier-types\";\nimport type { EffectiveLayer } from \"@a-company/atelier-canvas\";\nimport { buildGradientDef, colorToCSS } from \"./svg-gradients.js\";\n\n/** Render a shape visual as SVG elements */\nexport function renderShapeSVG(\n eff: EffectiveLayer,\n visual: ShapeVisual,\n): { elements: string; defs: string } {\n const { shape } = visual;\n const defs: string[] = [];\n\n let fillAttr = \"none\";\n if (visual.fill) {\n const gradResult = buildGradientDef(visual.fill, eff.width, eff.height);\n if (gradResult.defs) defs.push(gradResult.defs);\n fillAttr = gradResult.fillRef;\n }\n\n let strokeAttrs = \"\";\n if (visual.stroke) {\n strokeAttrs = buildStrokeAttrs(visual.stroke);\n }\n\n const element = buildShapeElement(shape, eff.width, eff.height, fillAttr, strokeAttrs);\n return { elements: element, defs: defs.join(\"\") };\n}\n\nfunction buildShapeElement(\n shape: Shape,\n width: number,\n height: number,\n fill: string,\n strokeAttrs: string,\n): string {\n switch (shape.type) {\n case \"rect\":\n return buildRectElement(shape, width, height, fill, strokeAttrs);\n case \"ellipse\":\n return buildEllipseElement(width, height, fill, strokeAttrs);\n case \"path\":\n return buildPathElement(shape, fill, strokeAttrs);\n }\n}\n\nfunction buildRectElement(\n shape: RectShape,\n width: number,\n height: number,\n fill: string,\n strokeAttrs: string,\n): string {\n let rx = \"\";\n if (shape.cornerRadius) {\n const r = typeof shape.cornerRadius === \"number\" ? shape.cornerRadius : shape.cornerRadius[0];\n rx = ` rx=\"${r}\" ry=\"${r}\"`;\n }\n return `<rect width=\"${width}\" height=\"${height}\" fill=\"${fill}\"${rx}${strokeAttrs ? \" \" + strokeAttrs : \"\"} />`;\n}\n\nfunction buildEllipseElement(\n width: number,\n height: number,\n fill: string,\n strokeAttrs: string,\n): string {\n const cx = width / 2;\n const cy = height / 2;\n const rx = width / 2;\n const ry = height / 2;\n return `<ellipse cx=\"${cx}\" cy=\"${cy}\" rx=\"${rx}\" ry=\"${ry}\" fill=\"${fill}\"${strokeAttrs ? \" \" + strokeAttrs : \"\"} />`;\n}\n\nfunction buildPathElement(\n shape: PathShape,\n fill: string,\n strokeAttrs: string,\n): string {\n if (shape.points.length < 2) return \"\";\n\n const d: string[] = [];\n d.push(`M ${shape.points[0].x} ${shape.points[0].y}`);\n\n for (let i = 1; i < shape.points.length; i++) {\n const prev = shape.points[i - 1];\n const curr = shape.points[i];\n\n if (prev.out && curr.in) {\n d.push(`C ${prev.x + prev.out.x} ${prev.y + prev.out.y} ${curr.x + curr.in.x} ${curr.y + curr.in.y} ${curr.x} ${curr.y}`);\n } else {\n d.push(`L ${curr.x} ${curr.y}`);\n }\n }\n\n if (shape.closed) d.push(\"Z\");\n\n return `<path d=\"${d.join(\" \")}\" fill=\"${fill}\"${strokeAttrs ? \" \" + strokeAttrs : \"\"} />`;\n}\n\nfunction buildStrokeAttrs(stroke: Stroke): string {\n const parts: string[] = [];\n parts.push(`stroke=\"${colorToCSS(stroke.color)}\"`);\n parts.push(`stroke-width=\"${stroke.width}\"`);\n\n if (stroke.lineCap) parts.push(`stroke-linecap=\"${stroke.lineCap}\"`);\n if (stroke.lineJoin) parts.push(`stroke-linejoin=\"${stroke.lineJoin}\"`);\n if (stroke.dash) parts.push(`stroke-dasharray=\"${stroke.dash.join(\" \")}\"`);\n\n return parts.join(\" \");\n}\n","import type { TextVisual } from \"@a-company/atelier-types\";\nimport type { EffectiveLayer } from \"@a-company/atelier-canvas\";\nimport { colorToCSS } from \"./svg-gradients.js\";\nimport { escapeXml } from \"./svg-properties.js\";\n\n/** Render a text visual as SVG elements */\nexport function renderTextSVG(eff: EffectiveLayer, visual: TextVisual): string {\n const { style } = visual;\n\n const attrs: string[] = [];\n\n // Font attributes\n attrs.push(`font-family=\"${escapeXml(style.fontFamily)}\"`);\n attrs.push(`font-size=\"${style.fontSize}\"`);\n\n if (style.fontWeight && style.fontWeight !== \"normal\") {\n attrs.push(`font-weight=\"${style.fontWeight}\"`);\n }\n if (style.fontStyle && style.fontStyle !== \"normal\") {\n attrs.push(`font-style=\"${style.fontStyle}\"`);\n }\n\n // Color\n attrs.push(`fill=\"${colorToCSS(style.color)}\"`);\n\n // Text alignment\n const align = style.textAlign ?? \"left\";\n let textAnchor = \"start\";\n let x = 0;\n if (align === \"center\") {\n textAnchor = \"middle\";\n x = eff.width / 2;\n } else if (align === \"right\") {\n textAnchor = \"end\";\n x = eff.width;\n }\n attrs.push(`text-anchor=\"${textAnchor}\"`);\n\n // Letter spacing\n if (style.letterSpacing) {\n attrs.push(`letter-spacing=\"${style.letterSpacing}\"`);\n }\n\n // SVG text baseline: use dominant-baseline for top alignment\n attrs.push(`dominant-baseline=\"hanging\"`);\n\n return `<text x=\"${x}\" y=\"0\" ${attrs.join(\" \")}>${escapeXml(visual.content)}</text>`;\n}\n","import type { EffectiveLayer } from \"@a-company/atelier-canvas\";\n\nlet filterIdCounter = 0;\n\nexport function resetFilterCounter(): void {\n filterIdCounter = 0;\n}\n\n/** Build SVG filter definition for shadow effects */\nexport function buildShadowFilter(eff: EffectiveLayer): { defs: string; filterRef: string } | null {\n if (!eff.shadow) return null;\n\n const id = `filter-${++filterIdCounter}`;\n const { color, blur, offsetX, offsetY } = eff.shadow;\n\n const def = [\n `<filter id=\"${id}\" x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">`,\n `<feDropShadow dx=\"${offsetX}\" dy=\"${offsetY}\" stdDeviation=\"${blur / 2}\" flood-color=\"${color}\" />`,\n `</filter>`,\n ].join(\"\");\n\n return { defs: def, filterRef: `url(#${id})` };\n}\n\n/** Build SVG filter definition for tint effect (feFlood + feBlend multiply) */\nexport function buildTintFilter(eff: EffectiveLayer): { defs: string; filterRef: string } | null {\n if (!eff.tint || eff.tint.amount <= 0) return null;\n\n const id = `filter-${++filterIdCounter}`;\n const { color, amount } = eff.tint;\n\n const def = [\n `<filter id=\"${id}\" x=\"0%\" y=\"0%\" width=\"100%\" height=\"100%\">`,\n `<feFlood flood-color=\"${color}\" flood-opacity=\"${amount}\" result=\"tint\" />`,\n `<feBlend in=\"SourceGraphic\" in2=\"tint\" mode=\"multiply\" />`,\n `</filter>`,\n ].join(\"\");\n\n return { defs: def, filterRef: `url(#${id})` };\n}\n","import type { Shape } from \"@a-company/atelier-types\";\n\nlet clipIdCounter = 0;\n\nexport function resetClipCounter(): void {\n clipIdCounter = 0;\n}\n\n/** Build SVG clipPath definition */\nexport function buildClipPathDef(shape: Shape, width: number, height: number): { defs: string; clipRef: string } {\n const id = `clip-${++clipIdCounter}`;\n let pathContent = \"\";\n\n switch (shape.type) {\n case \"rect\":\n if (shape.cornerRadius) {\n const r = typeof shape.cornerRadius === \"number\" ? shape.cornerRadius : shape.cornerRadius[0];\n pathContent = `<rect width=\"${width}\" height=\"${height}\" rx=\"${r}\" ry=\"${r}\" />`;\n } else {\n pathContent = `<rect width=\"${width}\" height=\"${height}\" />`;\n }\n break;\n case \"ellipse\":\n pathContent = `<ellipse cx=\"${width / 2}\" cy=\"${height / 2}\" rx=\"${width / 2}\" ry=\"${height / 2}\" />`;\n break;\n case \"path\": {\n if (shape.points.length < 2) return { defs: \"\", clipRef: \"\" };\n const d: string[] = [];\n d.push(`M ${shape.points[0].x} ${shape.points[0].y}`);\n for (let i = 1; i < shape.points.length; i++) {\n const prev = shape.points[i - 1];\n const curr = shape.points[i];\n if (prev.out && curr.in) {\n d.push(`C ${prev.x + prev.out.x} ${prev.y + prev.out.y} ${curr.x + curr.in.x} ${curr.y + curr.in.y} ${curr.x} ${curr.y}`);\n } else {\n d.push(`L ${curr.x} ${curr.y}`);\n }\n }\n if (shape.closed) d.push(\"Z\");\n pathContent = `<path d=\"${d.join(\" \")}\" />`;\n break;\n }\n }\n\n const def = `<clipPath id=\"${id}\">${pathContent}</clipPath>`;\n return { defs: def, clipRef: `url(#${id})` };\n}\n","import type { Color, RGBAColor, HSLAColor } from \"@a-company/atelier-types\";\n\n/** Convert an Atelier color to Lottie [r, g, b, a] format (0–1 range) */\nexport function colorToLottie(color: Color): number[] {\n if (typeof color === \"string\") {\n return hexToLottie(color);\n }\n\n if (\"r\" in color) {\n const c = color as RGBAColor;\n return [c.r / 255, c.g / 255, c.b / 255, c.a];\n }\n\n if (\"h\" in color) {\n const c = color as HSLAColor;\n const rgb = hslToRgb(c.h, c.s, c.l);\n return [rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, c.a];\n }\n\n return [0, 0, 0, 1];\n}\n\nfunction hexToLottie(hex: string): number[] {\n const clean = hex.replace(\"#\", \"\");\n if (clean.length === 3 || clean.length === 4) {\n const r = parseInt(clean[0] + clean[0], 16) / 255;\n const g = parseInt(clean[1] + clean[1], 16) / 255;\n const b = parseInt(clean[2] + clean[2], 16) / 255;\n const a = clean.length === 4 ? parseInt(clean[3] + clean[3], 16) / 255 : 1;\n return [r, g, b, a];\n }\n const r = parseInt(clean.slice(0, 2), 16) / 255;\n const g = parseInt(clean.slice(2, 4), 16) / 255;\n const b = parseInt(clean.slice(4, 6), 16) / 255;\n const a = clean.length === 8 ? parseInt(clean.slice(6, 8), 16) / 255 : 1;\n return [r, g, b, a];\n}\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n s = s / 100;\n l = l / 100;\n const a = s * Math.min(l, 1 - l);\n const f = (n: number) => {\n const k = (n + h / 30) % 12;\n return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);\n };\n return [Math.round(f(0) * 255), Math.round(f(8) * 255), Math.round(f(4) * 255)];\n}\n","import type { ShapeVisual, Fill, Stroke } from \"@a-company/atelier-types\";\nimport type { LottieShapeItem } from \"./lottie-types.js\";\nimport { colorToLottie } from \"./map-colors.js\";\n\n/** Map an Atelier shape visual to Lottie shape items */\nexport function mapShapeVisual(\n visual: ShapeVisual,\n width: number,\n height: number,\n): LottieShapeItem[] {\n const items: LottieShapeItem[] = [];\n\n // Shape geometry\n switch (visual.shape.type) {\n case \"rect\":\n items.push({\n ty: \"rc\",\n nm: \"Rectangle\",\n d: 1,\n s: { a: 0, k: [width, height] },\n p: { a: 0, k: [width / 2, height / 2] },\n r: { a: 0, k: typeof visual.shape.cornerRadius === \"number\" ? visual.shape.cornerRadius : 0 },\n });\n break;\n case \"ellipse\":\n items.push({\n ty: \"el\",\n nm: \"Ellipse\",\n d: 1,\n s: { a: 0, k: [width, height] },\n p: { a: 0, k: [width / 2, height / 2] },\n });\n break;\n case \"path\": {\n const vertices = visual.shape.points.map(p => [p.x, p.y]);\n const inTangents = visual.shape.points.map(p => p.in ? [p.in.x, p.in.y] : [0, 0]);\n const outTangents = visual.shape.points.map(p => p.out ? [p.out.x, p.out.y] : [0, 0]);\n items.push({\n ty: \"sh\",\n nm: \"Path\",\n ks: {\n a: 0,\n k: {\n c: visual.shape.closed ?? false,\n v: vertices,\n i: inTangents,\n o: outTangents,\n },\n },\n });\n break;\n }\n }\n\n // Fill\n if (visual.fill) {\n items.push(mapFill(visual.fill, width, height));\n }\n\n // Stroke\n if (visual.stroke) {\n items.push(mapStroke(visual.stroke));\n }\n\n return items;\n}\n\nfunction mapFill(fill: Fill, _width: number, _height: number): LottieShapeItem {\n if (fill.type === \"solid\") {\n const color = colorToLottie(fill.color);\n return {\n ty: \"fl\",\n nm: \"Fill\",\n c: { a: 0, k: color.slice(0, 3) },\n o: { a: 0, k: (color[3] ?? 1) * 100 },\n r: 1,\n };\n }\n\n if (fill.type === \"linear-gradient\") {\n const stops: number[] = [];\n for (const stop of fill.stops) {\n const c = colorToLottie(stop.color);\n stops.push(stop.offset, c[0], c[1], c[2]);\n }\n return {\n ty: \"gf\",\n nm: \"Gradient Fill\",\n t: 1, // linear\n s: { a: 0, k: [0, 0] },\n e: { a: 0, k: [100, 0] },\n g: { p: fill.stops.length, k: { a: 0, k: stops } },\n r: 1,\n o: { a: 0, k: 100 },\n };\n }\n\n if (fill.type === \"radial-gradient\") {\n const stops: number[] = [];\n for (const stop of fill.stops) {\n const c = colorToLottie(stop.color);\n stops.push(stop.offset, c[0], c[1], c[2]);\n }\n return {\n ty: \"gf\",\n nm: \"Gradient Fill\",\n t: 2, // radial\n s: { a: 0, k: [50, 50] },\n e: { a: 0, k: [100, 50] },\n g: { p: fill.stops.length, k: { a: 0, k: stops } },\n r: 1,\n o: { a: 0, k: 100 },\n };\n }\n\n return { ty: \"fl\", nm: \"Fill\", c: { a: 0, k: [0, 0, 0] }, o: { a: 0, k: 100 }, r: 1 };\n}\n\nfunction mapStroke(stroke: Stroke): LottieShapeItem {\n const color = colorToLottie(stroke.color);\n return {\n ty: \"st\",\n nm: \"Stroke\",\n c: { a: 0, k: color.slice(0, 3) },\n o: { a: 0, k: (color[3] ?? 1) * 100 },\n w: { a: 0, k: stroke.width },\n lc: stroke.lineCap === \"round\" ? 2 : stroke.lineCap === \"square\" ? 3 : 1,\n lj: stroke.lineJoin === \"round\" ? 2 : stroke.lineJoin === \"bevel\" ? 3 : 1,\n };\n}\n","import type { Easing } from \"@a-company/atelier-types\";\n\nexport interface LottieEasing {\n i: { x: number[]; y: number[] };\n o: { x: number[]; y: number[] };\n}\n\n/** Map an Atelier easing to Lottie bezier easing curves */\nexport function mapEasing(easing: Easing | undefined): LottieEasing | { h: 1 } {\n if (!easing) return linearEasing();\n\n if (typeof easing === \"string\") {\n switch (easing) {\n case \"ease-in\":\n return bezierEasing(0.42, 0, 1, 1);\n case \"ease-out\":\n return bezierEasing(0, 0, 0.58, 1);\n case \"ease-in-out\":\n return bezierEasing(0.42, 0, 0.58, 1);\n default:\n return linearEasing();\n }\n }\n\n switch (easing.type) {\n case \"linear\":\n return linearEasing();\n case \"cubic-bezier\":\n return bezierEasing(easing.x1, easing.y1, easing.x2, easing.y2);\n case \"spring\":\n // Approximate spring as a cubic-bezier (lossy)\n return bezierEasing(0.25, 0.1, 0.25, 1);\n case \"step\":\n // Steps map to hold keyframes\n return { h: 1 };\n default:\n return linearEasing();\n }\n}\n\nfunction linearEasing(): LottieEasing {\n return {\n i: { x: [0.833], y: [0.833] },\n o: { x: [0.167], y: [0.167] },\n };\n}\n\nfunction bezierEasing(x1: number, y1: number, x2: number, y2: number): LottieEasing {\n return {\n i: { x: [x2], y: [y2] },\n o: { x: [x1], y: [y1] },\n };\n}\n\n/** Check if an easing is lossy (spring/step → approximated) */\nexport function isLossyEasing(easing: Easing | undefined): string | null {\n if (!easing || typeof easing === \"string\") return null;\n if (easing.type === \"spring\") return \"Spring easing approximated as cubic-bezier\";\n if (easing.type === \"step\") return \"Step easing mapped to hold keyframes\";\n return null;\n}\n","import type { Delta, AnimatableProperty } from \"@a-company/atelier-types\";\nimport type { LottieAnimatedValue, LottieAnimatedMultiValue, LottieKeyframe, LottieMultiKeyframe } from \"./lottie-types.js\";\nimport { mapEasing, isLossyEasing } from \"./map-easing.js\";\n\n/** Map deltas for a single layer+property to Lottie animated value */\nexport function mapDeltasToAnimated(\n deltas: Delta[],\n property: AnimatableProperty,\n warnings: string[],\n): LottieAnimatedValue {\n if (deltas.length === 0) {\n return { a: 0, k: 0 };\n }\n\n // Check for lossy easings\n for (const d of deltas) {\n const lossyMsg = isLossyEasing(d.easing);\n if (lossyMsg) warnings.push(`${property}: ${lossyMsg}`);\n }\n\n // If expressions, warn and use static\n for (const d of deltas) {\n if (isExpression(d.from) || isExpression(d.to)) {\n warnings.push(`${property}: Expression values not supported in Lottie, using static values`);\n return { a: 0, k: typeof d.from === \"number\" ? d.from : 0 };\n }\n }\n\n // Single delta — simple animated value\n if (deltas.length === 1) {\n const d = deltas[0];\n const fromVal = resolveValue(d.from, property);\n const toVal = resolveValue(d.to, property);\n\n if (fromVal === toVal) {\n return { a: 0, k: fromVal };\n }\n\n const easing = mapEasing(d.easing);\n const kfs: LottieKeyframe[] = [];\n\n if (\"h\" in easing) {\n kfs.push({ t: d.range[0], s: [fromVal], h: 1 });\n kfs.push({ t: d.range[1], s: [toVal] });\n } else {\n kfs.push({ t: d.range[0], s: [fromVal], e: [toVal], i: easing.i, o: easing.o });\n kfs.push({ t: d.range[1], s: [toVal] });\n }\n\n return { a: 1, k: kfs };\n }\n\n // Multiple deltas — chain keyframes\n const sorted = [...deltas].sort((a, b) => a.range[0] - b.range[0]);\n const kfs: LottieKeyframe[] = [];\n\n for (const d of sorted) {\n const fromVal = resolveValue(d.from, property);\n const toVal = resolveValue(d.to, property);\n const easing = mapEasing(d.easing);\n\n if (\"h\" in easing) {\n kfs.push({ t: d.range[0], s: [fromVal], h: 1 });\n } else {\n kfs.push({ t: d.range[0], s: [fromVal], e: [toVal], i: easing.i, o: easing.o });\n }\n }\n\n // Final keyframe\n const last = sorted[sorted.length - 1];\n kfs.push({ t: last.range[1], s: [resolveValue(last.to, property)] });\n\n return { a: 1, k: kfs };\n}\n\n/** Map position deltas (frame.x, frame.y) to Lottie multi-dimensional animated value */\nexport function mapPositionDeltas(\n xDeltas: Delta[],\n yDeltas: Delta[],\n baseX: number,\n baseY: number,\n warnings: string[],\n): LottieAnimatedMultiValue {\n const hasXAnim = xDeltas.length > 0;\n const hasYAnim = yDeltas.length > 0;\n\n if (!hasXAnim && !hasYAnim) {\n return { a: 0, k: [baseX, baseY, 0] };\n }\n\n // Collect all unique frame points\n const frames = new Set<number>();\n for (const d of [...xDeltas, ...yDeltas]) {\n frames.add(d.range[0]);\n frames.add(d.range[1]);\n }\n const sortedFrames = [...frames].sort((a, b) => a - b);\n\n if (sortedFrames.length < 2) {\n return { a: 0, k: [baseX, baseY, 0] };\n }\n\n // Build multi-dimensional keyframes\n const kfs: LottieMultiKeyframe[] = [];\n for (let i = 0; i < sortedFrames.length; i++) {\n const f = sortedFrames[i];\n const x = resolveAtFrame(xDeltas, f, baseX);\n const y = resolveAtFrame(yDeltas, f, baseY);\n\n if (i < sortedFrames.length - 1) {\n const nextF = sortedFrames[i + 1];\n const nextX = resolveAtFrame(xDeltas, nextF, baseX);\n const nextY = resolveAtFrame(yDeltas, nextF, baseY);\n\n // Find the active delta's easing\n const activeX = xDeltas.find(d => d.range[0] <= f && d.range[1] >= f);\n const activeY = yDeltas.find(d => d.range[0] <= f && d.range[1] >= f);\n const easing = mapEasing(activeX?.easing ?? activeY?.easing);\n\n if (\"h\" in easing) {\n kfs.push({ t: f, s: [x, y, 0], h: 1 });\n } else {\n kfs.push({ t: f, s: [x, y, 0], e: [nextX, nextY, 0], i: easing.i, o: easing.o });\n }\n } else {\n kfs.push({ t: f, s: [x, y, 0] });\n }\n }\n\n // Check for lossy warnings\n for (const d of [...xDeltas, ...yDeltas]) {\n const msg = isLossyEasing(d.easing);\n if (msg) warnings.push(`position: ${msg}`);\n }\n\n return { a: 1, k: kfs };\n}\n\nfunction resolveAtFrame(deltas: Delta[], frame: number, base: number): number {\n for (const d of deltas) {\n if (frame >= d.range[0] && frame <= d.range[1]) {\n const from = typeof d.from === \"number\" ? d.from : base;\n const to = typeof d.to === \"number\" ? d.to : base;\n const progress = d.range[0] === d.range[1] ? 1 : (frame - d.range[0]) / (d.range[1] - d.range[0]);\n return from + (to - from) * progress;\n }\n }\n // Hold last completed value\n let lastCompleted: Delta | undefined;\n for (const d of deltas) {\n if (frame > d.range[1]) {\n if (!lastCompleted || d.range[1] > lastCompleted.range[1]) {\n lastCompleted = d;\n }\n }\n }\n if (lastCompleted) return typeof lastCompleted.to === \"number\" ? lastCompleted.to : base;\n return base;\n}\n\nfunction resolveValue(val: unknown, _property: AnimatableProperty): number {\n if (typeof val === \"number\") return val;\n if (typeof val === \"string\" && val.startsWith(\"#\")) {\n // Color — for Lottie, colors are handled separately\n return 0;\n }\n return 0;\n}\n\nfunction isExpression(val: unknown): boolean {\n return typeof val === \"object\" && val !== null && \"expr\" in val;\n}\n","import type { AtelierDocument, Layer, Delta, State, UnitValue } from \"@a-company/atelier-types\";\nimport type { LottieLayer, LottieTransform, LottieTextData } from \"./lottie-types.js\";\nimport { mapShapeVisual } from \"./map-shapes.js\";\nimport { mapDeltasToAnimated, mapPositionDeltas } from \"./map-keyframes.js\";\nimport { colorToLottie } from \"./map-colors.js\";\n\n/** Resolve a UnitValue to a plain number (percentages treated as 0 for Lottie) */\nfunction toNum(v: UnitValue): number {\n return typeof v === \"number\" ? v : 0;\n}\n\n/** Map all layers in a document+state to Lottie layers */\nexport function mapLayers(\n doc: AtelierDocument,\n state: State,\n warnings: string[],\n): LottieLayer[] {\n const layerIndexMap = new Map<string, number>();\n doc.layers.forEach((l, i) => layerIndexMap.set(l.id, i));\n\n return doc.layers.map((layer, index) => {\n const deltas = state.deltas.filter(d => d.layer === layer.id);\n return mapLayer(layer, index, deltas, layerIndexMap, doc, warnings);\n });\n}\n\nfunction mapLayer(\n layer: Layer,\n index: number,\n deltas: Delta[],\n layerIndexMap: Map<string, number>,\n doc: AtelierDocument,\n warnings: string[],\n): LottieLayer {\n const duration = getMaxFrame(deltas, doc);\n\n const base: LottieLayer = {\n ty: getLayerType(layer),\n nm: layer.id,\n ind: index,\n ip: 0,\n op: duration,\n st: 0,\n ks: buildTransform(layer, deltas, warnings),\n };\n\n // Parent\n if (layer.parentId) {\n const parentIdx = layerIndexMap.get(layer.parentId);\n if (parentIdx !== undefined) {\n base.parent = parentIdx;\n }\n }\n\n // Blend mode\n if (layer.blendMode) {\n base.bm = mapBlendMode(layer.blendMode);\n }\n\n // Shape layer\n if (layer.visual.type === \"shape\") {\n base.shapes = mapShapeVisual(layer.visual, toNum(layer.bounds.width), toNum(layer.bounds.height));\n }\n\n // Text layer\n if (layer.visual.type === \"text\") {\n const color = colorToLottie(layer.visual.style.color);\n base.t = {\n d: {\n k: [{\n s: {\n s: layer.visual.style.fontSize,\n f: layer.visual.style.fontFamily,\n t: layer.visual.content,\n fc: color.slice(0, 3),\n j: layer.visual.style.textAlign === \"center\" ? 1 :\n layer.visual.style.textAlign === \"right\" ? 2 : 0,\n },\n t: 0,\n }],\n },\n } as LottieTextData;\n }\n\n // Image layer\n if (layer.visual.type === \"image\") {\n base.refId = layer.visual.assetId;\n base.w = toNum(layer.bounds.width);\n base.h = toNum(layer.bounds.height);\n\n if (layer.visual.spritesheet) {\n warnings.push(`Layer \"${layer.id}\": Spritesheet animation not supported in Lottie export`);\n }\n if (layer.visual.sourceRect) {\n warnings.push(`Layer \"${layer.id}\": sourceRect cropping not supported in Lottie export`);\n }\n }\n\n // Tint warning\n if (layer.tint && layer.tint.amount > 0) {\n warnings.push(`Layer \"${layer.id}\": Tint effect not supported in Lottie export`);\n }\n\n return base;\n}\n\nfunction getLayerType(layer: Layer): number {\n switch (layer.visual.type) {\n case \"shape\": return 4;\n case \"text\": return 5;\n case \"image\": return 2;\n case \"group\": return 3; // null layer\n case \"ref\": return 0; // precomp\n default: return 4;\n }\n}\n\nfunction buildTransform(\n layer: Layer,\n deltas: Delta[],\n warnings: string[],\n): LottieTransform {\n // Group deltas by property\n const byProp = new Map<string, Delta[]>();\n for (const d of deltas) {\n if (!byProp.has(d.property)) byProp.set(d.property, []);\n byProp.get(d.property)!.push(d);\n }\n\n const xDeltas = byProp.get(\"frame.x\") ?? [];\n const yDeltas = byProp.get(\"frame.y\") ?? [];\n const opacityDeltas = byProp.get(\"opacity\") ?? [];\n const rotationDeltas = byProp.get(\"rotation\") ?? [];\n const scaleXDeltas = byProp.get(\"scale.x\") ?? [];\n const scaleYDeltas = byProp.get(\"scale.y\") ?? [];\n\n // Position\n const position = mapPositionDeltas(\n xDeltas, yDeltas,\n typeof layer.frame.x === \"number\" ? layer.frame.x : 0,\n typeof layer.frame.y === \"number\" ? layer.frame.y : 0,\n warnings,\n );\n\n // Opacity (Lottie uses 0–100)\n let opacity;\n if (opacityDeltas.length > 0) {\n const raw = mapDeltasToAnimated(opacityDeltas, \"opacity\", warnings);\n // Scale 0-1 to 0-100\n if (raw.a === 0) {\n opacity = { a: 0 as const, k: (raw.k as number) * 100 };\n } else {\n const kfs = (raw.k as Array<{ t: number; s: [number]; e?: [number]; [key: string]: unknown }>).map(kf => ({\n ...kf,\n s: [kf.s[0] * 100] as [number],\n e: kf.e ? [kf.e[0] * 100] as [number] : undefined,\n }));\n opacity = { a: 1 as const, k: kfs };\n }\n } else {\n opacity = { a: 0 as const, k: (layer.opacity ?? 1) * 100 };\n }\n\n // Rotation\n const rotation = rotationDeltas.length > 0\n ? mapDeltasToAnimated(rotationDeltas, \"rotation\", warnings)\n : { a: 0 as const, k: layer.rotation ?? 0 };\n\n // Scale (Lottie uses 0–100)\n const baseScaleX = (layer.scale?.x ?? 1) * 100;\n const baseScaleY = (layer.scale?.y ?? 1) * 100;\n let scale;\n if (scaleXDeltas.length > 0 || scaleYDeltas.length > 0) {\n // Simplified: use x deltas for now\n scale = { a: 0 as const, k: [baseScaleX, baseScaleY, 100] };\n if (scaleXDeltas.length > 0 || scaleYDeltas.length > 0) {\n warnings.push(\"Scale animation partially mapped to Lottie\");\n }\n } else {\n scale = { a: 0 as const, k: [baseScaleX, baseScaleY, 100] };\n }\n\n // Anchor point\n const ax = (layer.anchorPoint?.x ?? 0) * toNum(layer.bounds.width);\n const ay = (layer.anchorPoint?.y ?? 0) * toNum(layer.bounds.height);\n\n return {\n o: opacity,\n r: rotation,\n p: position,\n a: { a: 0, k: [ax, ay, 0] },\n s: scale,\n };\n}\n\nfunction getMaxFrame(deltas: Delta[], doc: AtelierDocument): number {\n let max = 0;\n for (const state of Object.values(doc.states)) {\n if (state.duration > max) max = state.duration;\n }\n for (const d of deltas) {\n if (d.range[1] > max) max = d.range[1];\n }\n return max || 60;\n}\n\nfunction mapBlendMode(mode: string): number {\n const map: Record<string, number> = {\n normal: 0, multiply: 1, screen: 2, overlay: 3,\n darken: 4, lighten: 5, \"color-dodge\": 6, \"color-burn\": 7,\n \"hard-light\": 8, \"soft-light\": 9, difference: 10, exclusion: 11,\n hue: 12, saturation: 13, color: 14, luminosity: 15,\n };\n return map[mode] ?? 0;\n}\n","import type { AtelierDocument, State } from \"@a-company/atelier-types\";\n\n/** Check for unsupported features and collect warnings */\nexport function collectUnsupportedWarnings(doc: AtelierDocument, state: State): string[] {\n const warnings: string[] = [];\n\n // Audio not supported\n if (state.audio) {\n warnings.push(\"Audio tracks are not supported in Lottie format and will be dropped\");\n }\n\n // Expressions not supported\n for (const delta of state.deltas) {\n if (isExpression(delta.from) || isExpression(delta.to)) {\n warnings.push(`Expression values on \"${delta.layer}.${delta.property}\" not supported in Lottie`);\n }\n }\n\n // Shadow not supported in base Lottie\n for (const layer of doc.layers) {\n if (layer.shadow) {\n warnings.push(`Shadow on layer \"${layer.id}\" is not supported in base Lottie format`);\n }\n }\n\n // Motion path not directly mapped\n for (const layer of doc.layers) {\n if (layer.motionPath) {\n warnings.push(`Motion path on layer \"${layer.id}\" is not directly mappable to Lottie`);\n }\n }\n\n // Clip paths have limited support\n for (const layer of doc.layers) {\n if (layer.clipPath) {\n warnings.push(`Clip path on layer \"${layer.id}\" mapped as Lottie mask (partial support)`);\n }\n }\n\n // States/transitions\n if (Object.keys(doc.states).length > 1) {\n warnings.push(\"Multiple states flattened to single timeline in Lottie export\");\n }\n\n return warnings;\n}\n\nfunction isExpression(val: unknown): boolean {\n return typeof val === \"object\" && val !== null && \"expr\" in val;\n}\n","import type { AtelierDocument } from \"@a-company/atelier-types\";\nimport type { LottieAnimation, LottieAsset } from \"./lottie-types.js\";\nimport { mapLayers } from \"./map-layers.js\";\nimport { collectUnsupportedWarnings } from \"./warnings.js\";\n\nexport interface ExportLottieOptions {\n /** State to export (defaults to first state) */\n state?: string;\n}\n\nexport interface ExportLottieResult {\n /** The Lottie JSON animation */\n json: LottieAnimation;\n /** Warnings about unsupported features */\n warnings: string[];\n}\n\n/**\n * Export an Atelier document to Lottie JSON format.\n * This is a lossy conversion — not all features are supported.\n */\nexport function exportToLottie(\n doc: AtelierDocument,\n opts?: ExportLottieOptions,\n): ExportLottieResult {\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) {\n throw new Error(\"Document has no states to export\");\n }\n\n const stateName = opts?.state ?? stateNames[0];\n const state = doc.states[stateName];\n if (!state) {\n throw new Error(`State \"${stateName}\" not found`);\n }\n\n const warnings: string[] = [];\n\n // Collect unsupported feature warnings\n warnings.push(...collectUnsupportedWarnings(doc, state));\n\n // Map layers\n const layers = mapLayers(doc, state, warnings);\n\n // Map assets\n const assets: LottieAsset[] = [];\n if (doc.assets) {\n for (const [id, asset] of Object.entries(doc.assets)) {\n if (asset.type === \"image\") {\n assets.push({\n id,\n w: 100,\n h: 100,\n p: asset.src,\n e: 0,\n });\n }\n }\n }\n\n const json: LottieAnimation = {\n v: \"5.7.4\",\n fr: doc.canvas.fps,\n ip: 0,\n op: state.duration,\n w: doc.canvas.width,\n h: doc.canvas.height,\n nm: doc.name,\n layers,\n ...(assets.length > 0 ? { assets } : {}),\n };\n\n // Deduplicate warnings\n const uniqueWarnings = [...new Set(warnings)];\n\n return { json, warnings: uniqueWarnings };\n}\n","// @a-company/atelier-mcp — Asset management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, ImageVisual } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_asset ─────────────────────────────────────────\n server.tool(\n \"atelier_add_asset\",\n \"Register an external asset (image, SVG, font, animation, audio) on a document\",\n {\n id: z.string().describe(\"Document ID\"),\n assetId: z.string().describe(\"Unique asset identifier\"),\n type: z.enum([\"image\", \"svg\", \"font\", \"animation\", \"audio\"]).describe(\"Asset type\"),\n src: z.string().describe(\"File path or URL\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n spritesheet: z.object({\n columns: z.number().int().positive().describe(\"Number of columns in the spritesheet grid\"),\n rows: z.number().int().positive().describe(\"Number of rows in the spritesheet grid\"),\n frameCount: z.number().int().positive().optional().describe(\"Total frame count (defaults to columns × rows)\"),\n frameWidth: z.number().positive().describe(\"Width of each frame in pixels\"),\n frameHeight: z.number().positive().describe(\"Height of each frame in pixels\"),\n }).optional().describe(\"Spritesheet metadata (image assets only)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, assetId, type, src, description, spritesheet }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.assets) doc.assets = {};\n if (doc.assets[assetId]) return err(`Asset \"${assetId}\" already exists`);\n\n doc.assets[assetId] = {\n type,\n src,\n ...(description !== undefined ? { description } : {}),\n ...(spritesheet ? { spritesheet } : {}),\n };\n return ok({ assetId, type, src });\n },\n );\n\n // ── atelier_list_assets ───────────────────────────────────────\n server.tool(\n \"atelier_list_assets\",\n \"List all registered assets with usage info (which layers/states reference them)\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const assets = doc.assets ?? {};\n const entries = Object.entries(assets).map(([assetId, asset]) => {\n // Find layers referencing this asset (ImageVisual.assetId)\n const referencingLayers = doc.layers\n .filter(l => l.visual.type === \"image\" && (l.visual as ImageVisual).assetId === assetId)\n .map(l => l.id);\n\n // Find states whose audio.src matches this assetId\n const referencingStates = Object.entries(doc.states)\n .filter(([, state]) => state.audio?.src === assetId)\n .map(([name]) => name);\n\n return {\n assetId,\n type: asset.type,\n src: asset.src,\n description: asset.description,\n usedByLayers: referencingLayers,\n usedByStates: referencingStates,\n };\n });\n\n return ok({ count: entries.length, assets: entries });\n },\n );\n\n // ── atelier_remove_asset ──────────────────────────────────────\n server.tool(\n \"atelier_remove_asset\",\n \"Remove a registered asset. Warns if layers or state audio still reference it.\",\n {\n id: z.string().describe(\"Document ID\"),\n assetId: z.string().describe(\"Asset ID to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, assetId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.assets?.[assetId]) return err(`Asset \"${assetId}\" not found`);\n\n const warnings: string[] = [];\n\n // Check layers referencing this asset\n const referencingLayers = doc.layers\n .filter(l => l.visual.type === \"image\" && (l.visual as ImageVisual).assetId === assetId)\n .map(l => l.id);\n if (referencingLayers.length > 0) {\n warnings.push(`Asset is referenced by layer(s): ${referencingLayers.join(\", \")}`);\n }\n\n // Check state audio referencing this asset\n const referencingStates = Object.entries(doc.states)\n .filter(([, state]) => state.audio?.src === assetId)\n .map(([name]) => name);\n if (referencingStates.length > 0) {\n warnings.push(`Asset is referenced by state audio: ${referencingStates.join(\", \")}`);\n }\n\n delete doc.assets[assetId];\n return ok({ assetId, warnings });\n },\n );\n}\n","// @a-company/atelier-mcp — Variable management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { findTemplateVariables } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_variable ──────────────────────────────────────\n server.tool(\n \"atelier_add_variable\",\n \"Define a template variable on a document\",\n {\n id: z.string().describe(\"Document ID\"),\n variableName: z.string().describe(\"Variable name (used in {{variableName}} patterns)\"),\n type: z.enum([\"string\", \"number\", \"color\", \"asset\", \"boolean\"]).describe(\"Variable type\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n default: z.unknown().optional().describe(\"Default value\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async (args) => {\n const result = getDoc(store, args.id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.variables) doc.variables = {};\n if (doc.variables[args.variableName]) return err(`Variable \"${args.variableName}\" already exists`);\n\n doc.variables[args.variableName] = {\n type: args.type,\n ...(args.description !== undefined ? { description: args.description } : {}),\n ...(args.default !== undefined ? { default: args.default } : {}),\n };\n return ok({ variableName: args.variableName, type: args.type });\n },\n );\n\n // ── atelier_list_variables ────────────────────────────────────\n server.tool(\n \"atelier_list_variables\",\n \"List all declared variables with usage info (which {{references}} exist in the document)\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const variables = doc.variables ?? {};\n const referenced = findTemplateVariables(doc);\n\n const entries = Object.entries(variables).map(([name, variable]) => ({\n name,\n type: variable.type,\n description: variable.description,\n default: variable.default,\n referenced: referenced.includes(name),\n }));\n\n const undeclared = referenced.filter(r => !variables[r]);\n\n return ok({ count: entries.length, variables: entries, undeclared });\n },\n );\n\n // ── atelier_remove_variable ───────────────────────────────────\n server.tool(\n \"atelier_remove_variable\",\n \"Remove a declared variable. Warns if {{references}} still exist in the document.\",\n {\n id: z.string().describe(\"Document ID\"),\n variableName: z.string().describe(\"Variable name to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, variableName }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.variables?.[variableName]) return err(`Variable \"${variableName}\" not found`);\n\n const warnings: string[] = [];\n const referenced = findTemplateVariables(doc);\n if (referenced.includes(variableName)) {\n warnings.push(`Variable \"{{${variableName}}}\" is still referenced in the document`);\n }\n\n delete doc.variables[variableName];\n if (Object.keys(doc.variables).length === 0) {\n doc.variables = undefined;\n }\n return ok({ variableName, warnings });\n },\n );\n}\n","// @a-company/atelier-mcp — Interaction management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Interaction } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_interaction ───────────────────────────────────\n server.tool(\n \"atelier_add_interaction\",\n \"Add a trigger-action interaction to a layer (click, hover, timer, signal → go-to-state, emit-signal, set-variable, toggle-visibility)\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer to attach the interaction to\"),\n interactionId: z.string().describe(\"Unique interaction ID\"),\n trigger: z.object({\n type: z.enum([\"click\", \"hover\", \"pointerdown\", \"pointerup\", \"timer\", \"signal\"]).describe(\"Trigger type\"),\n delay: z.number().optional().describe(\"Delay in ms (timer trigger only)\"),\n signal: z.string().optional().describe(\"Signal name (signal trigger only)\"),\n }).describe(\"What triggers the interaction\"),\n action: z.object({\n type: z.enum([\"go-to-state\", \"emit-signal\", \"set-variable\", \"toggle-visibility\"]).describe(\"Action type\"),\n state: z.string().optional().describe(\"Target state (go-to-state only)\"),\n signal: z.string().optional().describe(\"Signal to emit (emit-signal only)\"),\n variable: z.string().optional().describe(\"Variable name (set-variable only)\"),\n value: z.unknown().optional().describe(\"Value to set (set-variable only)\"),\n targetLayer: z.string().optional().describe(\"Target layer ID (toggle-visibility, defaults to self)\"),\n }).describe(\"What happens when triggered\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, interactionId, trigger, action, description }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (!layer.interactions) layer.interactions = [];\n if (layer.interactions.some(i => i.id === interactionId)) {\n return err(`Interaction \"${interactionId}\" already exists on layer \"${layerId}\"`);\n }\n\n // Validate trigger-specific fields\n if (trigger.type === \"timer\" && trigger.delay === undefined) {\n return err(\"Timer trigger requires a delay\");\n }\n if (trigger.type === \"signal\" && !trigger.signal) {\n return err(\"Signal trigger requires a signal name\");\n }\n\n // Validate action-specific fields\n if (action.type === \"go-to-state\") {\n if (!action.state) return err(\"go-to-state action requires a state name\");\n if (!doc.states[action.state]) return err(`Target state \"${action.state}\" not found`);\n }\n if (action.type === \"emit-signal\" && !action.signal) {\n return err(\"emit-signal action requires a signal name\");\n }\n if (action.type === \"set-variable\") {\n if (!action.variable) return err(\"set-variable action requires a variable name\");\n if (action.value === undefined) return err(\"set-variable action requires a value\");\n }\n if (action.type === \"toggle-visibility\" && action.targetLayer) {\n if (!doc.layers.find(l => l.id === action.targetLayer)) {\n return err(`Target layer \"${action.targetLayer}\" not found`);\n }\n }\n\n const interaction: Interaction = {\n id: interactionId,\n trigger: trigger as Interaction[\"trigger\"],\n action: action as Interaction[\"action\"],\n ...(description !== undefined ? { description } : {}),\n };\n\n layer.interactions.push(interaction);\n return ok({ layerId, interactionId, triggerType: trigger.type, actionType: action.type });\n },\n );\n\n // ── atelier_list_interactions ─────────────────────────────────\n server.tool(\n \"atelier_list_interactions\",\n \"List all interactions across all layers or for a specific layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().optional().describe(\"Optional: filter to a specific layer\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, layerId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layers = layerId\n ? doc.layers.filter(l => l.id === layerId)\n : doc.layers;\n\n if (layerId && layers.length === 0) return err(`Layer \"${layerId}\" not found`);\n\n const interactions = layers.flatMap(l =>\n (l.interactions ?? []).map(i => ({\n layerId: l.id,\n interactionId: i.id,\n triggerType: i.trigger.type,\n actionType: i.action.type,\n description: i.description,\n trigger: i.trigger,\n action: i.action,\n })),\n );\n\n return ok({ count: interactions.length, interactions });\n },\n );\n\n // ── atelier_remove_interaction ────────────────────────────────\n server.tool(\n \"atelier_remove_interaction\",\n \"Remove an interaction from a layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n interactionId: z.string().describe(\"Interaction ID to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, layerId, interactionId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (!layer.interactions) return err(`Interaction \"${interactionId}\" not found on layer \"${layerId}\"`);\n\n const idx = layer.interactions.findIndex(i => i.id === interactionId);\n if (idx === -1) return err(`Interaction \"${interactionId}\" not found on layer \"${layerId}\"`);\n\n layer.interactions.splice(idx, 1);\n if (layer.interactions.length === 0) {\n layer.interactions = undefined;\n }\n return ok({ layerId, interactionId, remainingInteractions: layer.interactions?.length ?? 0 });\n },\n );\n}\n","// @a-company/atelier-mcp — Ref layer (composition/nesting) tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, RefVisual } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_set_ref ───────────────────────────────────────────\n server.tool(\n \"atelier_set_ref\",\n \"Set the source reference on a ref-type layer. Can point to a file path or another in-memory document ID.\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID (must be a ref visual)\"),\n src: z.string().describe(\"File path, URL, or in-memory document ID\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, src }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"ref\") return err(`Layer \"${layerId}\" is type \"${layer.visual.type}\", not \"ref\"`);\n\n // Prevent self-reference\n if (src === id) return err(\"Cannot reference self — would cause infinite recursion\");\n\n (layer.visual as RefVisual).src = src;\n\n // Check if src is an in-memory document\n const isInMemory = store.has(src);\n return ok({ layerId, src, resolvedInMemory: isInMemory });\n },\n );\n\n // ── atelier_resolve_refs ──────────────────────────────────────\n server.tool(\n \"atelier_resolve_refs\",\n \"Check which ref layers can be resolved (point to valid in-memory documents)\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const refs = doc.layers\n .filter(l => l.visual.type === \"ref\")\n .map(l => {\n const src = (l.visual as RefVisual).src;\n const resolved = store.has(src);\n const targetDoc = resolved ? store.get(src) : undefined;\n return {\n layerId: l.id,\n src,\n resolved,\n targetName: targetDoc?.name,\n targetLayerCount: targetDoc?.layers.length,\n targetStateCount: targetDoc ? Object.keys(targetDoc.states).length : undefined,\n };\n });\n\n const resolvedCount = refs.filter(r => r.resolved).length;\n return ok({ count: refs.length, resolvedCount, refs });\n },\n );\n}\n","// @a-company/atelier-mcp — Performance tools (profiling, frame diff, batch preview)\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { resolveFrame } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_profile ─────────────────────────────────────────\n server.tool(\n \"atelier_profile\",\n \"Profile frame resolution performance — returns timing, layer count, property count, and delta count for a frame\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to profile\"),\n frame: z.number().int().min(0).describe(\"Frame number to resolve\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frame }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) {\n return err(`State \"${stateName}\" not found`);\n }\n\n const state = doc.states[stateName];\n const deltaCount = state.deltas.length;\n const expressionCount = state.deltas.filter(\n d => (typeof d.from === \"object\" && d.from !== null && \"expr\" in d.from) ||\n (typeof d.to === \"object\" && d.to !== null && \"expr\" in d.to)\n ).length;\n\n const start = performance.now();\n const resolved = resolveFrame(doc, stateName, frame);\n const resolveTimeMs = performance.now() - start;\n\n let propertiesComputed = 0;\n const layerDetails = resolved.layers.map(rl => {\n const propCount = Object.keys(rl.computedProperties).length;\n propertiesComputed += propCount;\n return {\n id: rl.id,\n visualType: rl.layer.visual.type,\n propertiesComputed: propCount,\n properties: Object.keys(rl.computedProperties),\n };\n });\n\n return ok({\n stateName,\n frame,\n duration: state.duration,\n resolveTimeMs: Math.round(resolveTimeMs * 1000) / 1000,\n layerCount: doc.layers.length,\n deltaCount,\n expressionCount,\n propertiesComputed,\n layerDetails,\n });\n },\n );\n\n // ── atelier_diff_frames ────────────────────────────────────\n server.tool(\n \"atelier_diff_frames\",\n \"Compare two frames and return only the properties that changed between them\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n frameA: z.number().int().min(0).describe(\"First frame number\"),\n frameB: z.number().int().min(0).describe(\"Second frame number\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frameA, frameB }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) {\n return err(`State \"${stateName}\" not found`);\n }\n\n const resolvedA = resolveFrame(doc, stateName, frameA);\n const resolvedB = resolveFrame(doc, stateName, frameB);\n\n const changes: Array<{\n layerId: string;\n property: string;\n from: unknown;\n to: unknown;\n }> = [];\n\n for (const layerB of resolvedB.layers) {\n const layerA = resolvedA.layers.find(l => l.id === layerB.id);\n const propsA = layerA?.computedProperties ?? {};\n const propsB = layerB.computedProperties;\n\n // All property keys from both frames\n const allKeys = new Set([...Object.keys(propsA), ...Object.keys(propsB)]);\n for (const key of allKeys) {\n const valA = (propsA as Record<string, unknown>)[key];\n const valB = (propsB as Record<string, unknown>)[key];\n if (valA !== valB) {\n changes.push({ layerId: layerB.id, property: key, from: valA, to: valB });\n }\n }\n }\n\n return ok({\n stateName,\n frameA,\n frameB,\n changeCount: changes.length,\n changes,\n });\n },\n );\n\n // ── atelier_batch_preview ──────────────────────────────────\n server.tool(\n \"atelier_batch_preview\",\n \"Preview multiple frames at once — reduces round-trips for scrubbing or timeline inspection\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to preview\"),\n frames: z.array(z.number().int().min(0)).min(1).max(60).describe(\"Array of frame numbers to resolve (max 60)\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frames }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) {\n return err(`State \"${stateName}\" not found`);\n }\n\n const start = performance.now();\n\n const results = frames.map(frame => {\n const resolved = resolveFrame(doc, stateName, frame);\n return {\n frame,\n layers: resolved.layers.map(rl => ({\n id: rl.id,\n computedProperties: rl.computedProperties,\n })),\n };\n });\n\n const totalTimeMs = performance.now() - start;\n\n return ok({\n stateName,\n duration: doc.states[stateName].duration,\n frameCount: frames.length,\n totalTimeMs: Math.round(totalTimeMs * 1000) / 1000,\n avgTimeMs: Math.round((totalTimeMs / frames.length) * 1000) / 1000,\n frames: results,\n });\n },\n );\n\n // ── atelier_complexity ─────────────────────────────────────\n server.tool(\n \"atelier_complexity\",\n \"Analyze document complexity — layer count, delta count, expression usage, state hierarchy depth\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layerCount = doc.layers.length;\n const stateCount = Object.keys(doc.states).length;\n const assetCount = doc.assets ? Object.keys(doc.assets).length : 0;\n const variableCount = doc.variables ? Object.keys(doc.variables).length : 0;\n\n let totalDeltas = 0;\n let totalExpressions = 0;\n let maxStateDuration = 0;\n let totalInteractions = 0;\n\n const stateDetails: Array<{\n name: string;\n duration: number;\n deltaCount: number;\n expressionCount: number;\n hasAudio: boolean;\n hasParent: boolean;\n transitionCount: number;\n }> = [];\n\n for (const [name, state] of Object.entries(doc.states)) {\n const deltaCount = state.deltas.length;\n totalDeltas += deltaCount;\n\n const expressionCount = state.deltas.filter(\n d => (typeof d.from === \"object\" && d.from !== null && \"expr\" in d.from) ||\n (typeof d.to === \"object\" && d.to !== null && \"expr\" in d.to)\n ).length;\n totalExpressions += expressionCount;\n\n if (state.duration > maxStateDuration) maxStateDuration = state.duration;\n\n stateDetails.push({\n name,\n duration: state.duration,\n deltaCount,\n expressionCount,\n hasAudio: !!state.audio,\n hasParent: !!state.parent,\n transitionCount: state.transitions ? Object.keys(state.transitions).length : 0,\n });\n }\n\n for (const layer of doc.layers) {\n if (layer.interactions) totalInteractions += layer.interactions.length;\n }\n\n // Compute hierarchy depth\n let maxHierarchyDepth = 0;\n for (const [name] of Object.entries(doc.states)) {\n let depth = 0;\n let current = name;\n const visited = new Set<string>();\n while (doc.states[current]?.parent && !visited.has(current)) {\n visited.add(current);\n current = doc.states[current].parent!;\n depth++;\n }\n if (depth > maxHierarchyDepth) maxHierarchyDepth = depth;\n }\n\n // Unique animated properties\n const animatedProperties = new Set<string>();\n for (const state of Object.values(doc.states)) {\n for (const delta of state.deltas) {\n animatedProperties.add(delta.property);\n }\n }\n\n return ok({\n layerCount,\n stateCount,\n totalDeltas,\n totalExpressions,\n totalInteractions,\n assetCount,\n variableCount,\n maxStateDuration,\n maxHierarchyDepth,\n uniqueAnimatedProperties: [...animatedProperties],\n stateDetails,\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Overlay layer tools (handle, page-number)\n//\n// Convenience tools for agents that build social-feed style overlays\n// (creator handle, \"1/5\" page indicator). Both tools tag emitted layers\n// \"overlay\" so re-running recipe pipelines (applyRecipeToOverlay) won't\n// destroy user-tweaked overlays — the same tag-namespace isolation\n// invariant used by silence-trim and caption layers.\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Layer, TextStyle } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nconst AnchorEnum = z.enum([\"top-left\", \"top-right\", \"bottom-left\", \"bottom-right\"]);\n\n// Mirrors recipe OverlayTextStyle (snake_case). Kept loose — partial overrides\n// merge over the runtime defaults below.\nconst OverlayStyleSchema = z.object({\n font_family: z.string().optional(),\n font_size: z.number().positive().optional(),\n font_weight: z.union([z.number(), z.enum([\"normal\", \"bold\"])]).optional(),\n color: z.string().optional(),\n}).optional();\n\nconst DEFAULT_OVERLAY_MARGIN = 24;\nconst DEFAULT_TEXT_STYLE: TextStyle = {\n fontFamily: \"Inter\",\n fontSize: 24,\n fontWeight: 600,\n color: \"#F5F5F7\",\n};\n\ntype Anchor = z.infer<typeof AnchorEnum>;\ntype OverlayStyleInput = {\n font_family?: string;\n font_size?: number;\n font_weight?: number | \"normal\" | \"bold\";\n color?: string;\n};\n\nfunction anchorToFrame(\n anchor: Anchor,\n canvas: AtelierDocument[\"canvas\"],\n margin: number,\n): { frame: { x: number; y: number }; anchorPoint: { x: number; y: number } } {\n switch (anchor) {\n case \"top-left\":\n return { frame: { x: margin, y: margin }, anchorPoint: { x: 0, y: 0 } };\n case \"top-right\":\n return { frame: { x: canvas.width - margin, y: margin }, anchorPoint: { x: 1, y: 0 } };\n case \"bottom-left\":\n return { frame: { x: margin, y: canvas.height - margin }, anchorPoint: { x: 0, y: 1 } };\n case \"bottom-right\":\n return {\n frame: { x: canvas.width - margin, y: canvas.height - margin },\n anchorPoint: { x: 1, y: 1 },\n };\n }\n}\n\nfunction mergeStyle(style: OverlayStyleInput | undefined): TextStyle {\n return {\n fontFamily: style?.font_family ?? DEFAULT_TEXT_STYLE.fontFamily,\n fontSize: style?.font_size ?? DEFAULT_TEXT_STYLE.fontSize,\n fontWeight: style?.font_weight ?? DEFAULT_TEXT_STYLE.fontWeight,\n color: style?.color ?? DEFAULT_TEXT_STYLE.color,\n };\n}\n\n/**\n * Render a page-number format template — substitutes {current} / {total}\n * placeholders including zero-pad forms ({current:02d}, {total:02d}).\n * Mirrors recipe.ts's renderPageNumberFormat exactly (intentional duplication\n * to keep the mcp package independent of the cli package).\n */\nfunction renderPageNumberFormat(format: string, currentIndex: number, totalCount: number): string {\n return format.replace(\n /\\{(current|total)(?::0(\\d+)d)?\\}/g,\n (_, name: string, padWidth?: string) => {\n const value = name === \"current\" ? currentIndex : totalCount;\n const str = String(value);\n if (padWidth) {\n const width = parseInt(padWidth, 10);\n return str.padStart(width, \"0\");\n }\n return str;\n },\n );\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_handle ──────────────────────────────────────\n server.tool(\n \"atelier_add_handle\",\n \"Add an anchored creator-handle TextVisual overlay layer (tag: overlay)\",\n {\n id: z.string().describe(\"Document ID\"),\n text: z.string().min(1).describe(\"Handle text, e.g. \\\"@username\\\"\"),\n anchor: AnchorEnum.describe(\"Anchored corner\"),\n margin: z.number().nonnegative().optional().describe(\"Px from anchored edges (default 24)\"),\n style: OverlayStyleSchema.describe(\"Text style overrides (snake_case to match recipe)\"),\n layerId: z.string().optional().describe(\"Layer ID (default: overlay-handle)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, text, anchor, margin, style, layerId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const targetId = layerId ?? \"overlay-handle\";\n if (doc.layers.some((l) => l.id === targetId)) {\n return err(`Layer \"${targetId}\" already exists in document \"${id}\"`);\n }\n\n const m = margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(anchor, doc.canvas, m);\n const layer: Layer = {\n id: targetId,\n tags: [\"overlay\"],\n visual: { type: \"text\", content: text, style: mergeStyle(style) },\n frame,\n bounds: { width: 600, height: 80 },\n anchorPoint,\n };\n\n doc.layers.push(layer);\n store.set(id, doc);\n return ok({ layerId: targetId, layer });\n },\n );\n\n // ── atelier_add_page_number ─────────────────────────────────\n server.tool(\n \"atelier_add_page_number\",\n \"Add an anchored page-number TextVisual overlay layer (tag: overlay). \" +\n \"Substitutes {current} / {total} (and zero-pad forms {current:02d} / {total:02d}) into format.\",\n {\n id: z.string().describe(\"Document ID\"),\n format: z.string().min(1).describe(\"Format string, e.g. \\\"{current}/{total}\\\" or \\\"{current:02d}/{total:02d}\\\"\"),\n anchor: AnchorEnum.describe(\"Anchored corner\"),\n currentIndex: z.number().int().nonnegative().describe(\"1-based current index\"),\n totalCount: z.number().int().positive().describe(\"Total count\"),\n margin: z.number().nonnegative().optional().describe(\"Px from anchored edges (default 24)\"),\n style: OverlayStyleSchema.describe(\"Text style overrides (snake_case to match recipe)\"),\n layerId: z.string().optional().describe(\"Layer ID (default: overlay-page-number)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, format, anchor, currentIndex, totalCount, margin, style, layerId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const targetId = layerId ?? \"overlay-page-number\";\n if (doc.layers.some((l) => l.id === targetId)) {\n return err(`Layer \"${targetId}\" already exists in document \"${id}\"`);\n }\n\n const content = renderPageNumberFormat(format, currentIndex, totalCount);\n const m = margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(anchor, doc.canvas, m);\n const layer: Layer = {\n id: targetId,\n tags: [\"overlay\"],\n visual: { type: \"text\", content, style: mergeStyle(style) },\n frame,\n bounds: { width: 200, height: 80 },\n anchorPoint,\n };\n\n doc.layers.push(layer);\n store.set(id, doc);\n return ok({ layerId: targetId, layer, rendered: content });\n },\n );\n}\n","// @a-company/atelier-mcp — Studio Recipe tools (list, get, validate, save, apply)\n//\n// Conversational view/edit surface for Studio Recipes. Wraps the recipe\n// load/validate/serialize/apply pipeline so an agent can show, explain, edit,\n// and apply recipes without shelling out to the CLI.\n//\n// Dependency note: the canonical recipe pure-functions live in the CLI package\n// (@a-company/atelier — packages/cli/src/lib/recipe.ts). The MCP package does\n// NOT depend on the CLI package (importing it would risk a cli↔mcp dependency\n// cycle), so the thin load/validate/serialize wrappers and the overlay_rules\n// translator are re-implemented here on top of @a-company/atelier-schema's\n// validateRecipe + the `yaml` package. This mirrors the existing intentional\n// duplication of renderPageNumberFormat in overlays.ts.\n\nimport { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from \"node:fs\";\nimport { join, resolve, isAbsolute, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { validateRecipe } from \"@a-company/atelier-schema\";\nimport type {\n AtelierDocument,\n Layer,\n StudioRecipe,\n OverlayAnchor,\n OverlayTextStyle,\n OverlayPageNumberRule,\n} from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string, extra?: Record<string, unknown>) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: message, ...extra }) }],\n isError: true as const,\n };\n}\n\n// ─── Recipe load / validate / serialize (re-implemented from cli/recipe.ts) ───\n\ninterface LoadedRecipe {\n recipe: StudioRecipe;\n /** Absolute path the recipe was read from */\n path: string;\n /** Warnings from validateRecipe (e.g. reserved-field usage) */\n warnings: string[];\n}\n\n/**\n * Resolve a recipe reference to an absolute path. Mirrors recipe.ts's\n * resolveRecipePath: absolute or slash-bearing paths load literally; bare\n * names resolve against <projectDir>/.atelier/recipes/ then ~/.atelier/recipes/.\n */\nfunction resolveRecipePath(pathOrName: string, projectDir: string): string {\n if (isAbsolute(pathOrName) || pathOrName.includes(\"/\") || pathOrName.includes(\"\\\\\")) {\n return resolve(pathOrName);\n }\n\n const candidates: string[] = [];\n const exts = [\".recipe.yaml\", \".recipe.json\", \".yaml\", \".yml\", \".json\"];\n\n const projectRecipesDir = join(resolve(projectDir), \".atelier\", \"recipes\");\n for (const ext of exts) candidates.push(join(projectRecipesDir, `${pathOrName}${ext}`));\n const userRecipesDir = join(homedir(), \".atelier\", \"recipes\");\n for (const ext of exts) candidates.push(join(userRecipesDir, `${pathOrName}${ext}`));\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) return candidate;\n }\n\n throw new Error(\n `Recipe \"${pathOrName}\" not found. Looked in:\\n${candidates.map((c) => ` ${c}`).join(\"\\n\")}`,\n );\n}\n\n/** Parse raw recipe text — JSON for .json, YAML otherwise (YAML is a JSON superset). */\nfunction parseRecipeText(raw: string, path: string): unknown {\n if (path.endsWith(\".json\")) return JSON.parse(raw);\n return parseYaml(raw);\n}\n\n/** Load + validate a recipe from a path or name. Throws on not-found / invalid. */\nfunction loadRecipe(pathOrName: string, projectDir: string): LoadedRecipe {\n const path = resolveRecipePath(pathOrName, projectDir);\n const raw = readFileSync(path, \"utf-8\");\n const parsed = parseRecipeText(raw, path);\n\n const result = validateRecipe(parsed);\n if (!result.success) {\n const msg = result.errors.map((e) => ` ${e.path}: ${e.message}`).join(\"\\n\");\n throw new Error(`Invalid recipe at ${path}:\\n${msg}`);\n }\n\n return { recipe: result.data, path, warnings: result.warnings ?? [] };\n}\n\n/** Serialize a recipe object back to YAML. */\nfunction recipeToYaml(recipe: StudioRecipe): string {\n return stringifyYaml(recipe);\n}\n\n// ─── Overlay translator (re-implemented from cli/recipe.ts) ───────────────────\n//\n// Translates recipe.overlay_rules → tag-isolated TextVisual layers. Only\n// \"overlay\"-tagged layers are touched; everything else passes through. Re-apply\n// is idempotent (prior overlay set dropped before fresh set appended).\n\nconst DEFAULT_OVERLAY_MARGIN = 24;\nconst DEFAULT_OVERLAY_TEXT_STYLE = {\n fontFamily: \"Inter\",\n fontSize: 24,\n fontWeight: 600 as const,\n color: \"#F5F5F7\",\n};\nconst HANDLE_LAYER_ID = \"overlay-handle\";\nconst PAGE_NUMBER_LAYER_ID = \"overlay-page-number\";\n\ninterface ApplyOverlayContext {\n currentIndex?: number;\n totalCount?: number;\n}\n\ninterface OverlayApplyResult {\n doc: AtelierDocument;\n warnings: string[];\n}\n\nfunction applyRecipeToOverlay(\n doc: AtelierDocument,\n recipe: StudioRecipe,\n ctx?: ApplyOverlayContext,\n): OverlayApplyResult {\n const preserved = doc.layers.filter((l) => !(l.tags ?? []).includes(\"overlay\"));\n const overlayLayers: Layer[] = [];\n const warnings: string[] = [];\n\n const rules = recipe.overlay_rules;\n if (!rules) {\n return { doc: { ...doc, layers: preserved }, warnings };\n }\n\n if (rules.handle) {\n overlayLayers.push(buildHandleLayer(rules.handle, doc.canvas));\n }\n\n if (rules.page_number) {\n if (ctx?.currentIndex != null && ctx?.totalCount != null) {\n overlayLayers.push(\n buildPageNumberLayer(rules.page_number, doc.canvas, ctx.currentIndex, ctx.totalCount),\n );\n } else {\n warnings.push(\n \"recipe.overlay_rules.page_number is present but currentIndex/totalCount \" +\n \"were not provided — the page_number layer was skipped.\",\n );\n }\n }\n\n return { doc: { ...doc, layers: [...preserved, ...overlayLayers] }, warnings };\n}\n\nfunction buildHandleLayer(\n rule: { text: string; anchor: OverlayAnchor; margin?: number; style?: OverlayTextStyle },\n canvas: AtelierDocument[\"canvas\"],\n): Layer {\n const margin = rule.margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(rule.anchor, canvas, margin);\n return {\n id: HANDLE_LAYER_ID,\n tags: [\"overlay\"],\n visual: { type: \"text\", content: rule.text, style: mergeOverlayStyle(rule.style) },\n frame,\n bounds: { width: 600, height: 80 },\n anchorPoint,\n };\n}\n\nfunction buildPageNumberLayer(\n rule: OverlayPageNumberRule,\n canvas: AtelierDocument[\"canvas\"],\n currentIndex: number,\n totalCount: number,\n): Layer {\n const margin = rule.margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(rule.anchor, canvas, margin);\n return {\n id: PAGE_NUMBER_LAYER_ID,\n tags: [\"overlay\"],\n visual: {\n type: \"text\",\n content: renderPageNumberFormat(rule.format, currentIndex, totalCount),\n style: mergeOverlayStyle(rule.style),\n },\n frame,\n bounds: { width: 200, height: 80 },\n anchorPoint,\n };\n}\n\nfunction anchorToFrame(\n anchor: OverlayAnchor,\n canvas: AtelierDocument[\"canvas\"],\n margin: number,\n): { frame: { x: number; y: number }; anchorPoint: { x: number; y: number } } {\n switch (anchor) {\n case \"top-left\":\n return { frame: { x: margin, y: margin }, anchorPoint: { x: 0, y: 0 } };\n case \"top-right\":\n return { frame: { x: canvas.width - margin, y: margin }, anchorPoint: { x: 1, y: 0 } };\n case \"bottom-left\":\n return { frame: { x: margin, y: canvas.height - margin }, anchorPoint: { x: 0, y: 1 } };\n case \"bottom-right\":\n return {\n frame: { x: canvas.width - margin, y: canvas.height - margin },\n anchorPoint: { x: 1, y: 1 },\n };\n }\n}\n\nfunction mergeOverlayStyle(\n style: OverlayTextStyle | undefined,\n): { fontFamily: string; fontSize: number; fontWeight: number | \"normal\" | \"bold\"; color: string } {\n return {\n fontFamily: style?.font_family ?? DEFAULT_OVERLAY_TEXT_STYLE.fontFamily,\n fontSize: style?.font_size ?? DEFAULT_OVERLAY_TEXT_STYLE.fontSize,\n fontWeight: style?.font_weight ?? DEFAULT_OVERLAY_TEXT_STYLE.fontWeight,\n color: style?.color ?? DEFAULT_OVERLAY_TEXT_STYLE.color,\n };\n}\n\nfunction renderPageNumberFormat(format: string, currentIndex: number, totalCount: number): string {\n return format.replace(\n /\\{(current|total)(?::0(\\d+)d)?\\}/g,\n (_, name: string, padWidth?: string) => {\n const value = name === \"current\" ? currentIndex : totalCount;\n const str = String(value);\n if (padWidth) return str.padStart(parseInt(padWidth, 10), \"0\");\n return str;\n },\n );\n}\n\n// ─── Discovery ────────────────────────────────────────────────────────────────\n\nconst RECIPE_EXTS = [\".recipe.yaml\", \".recipe.yml\", \".recipe.json\"];\n\nfunction isRecipeFile(name: string): boolean {\n return RECIPE_EXTS.some((ext) => name.endsWith(ext));\n}\n\n/** List recipe files in a directory (non-recursive). Returns absolute paths. */\nfunction listRecipesIn(dir: string): Array<{ name: string; path: string }> {\n if (!existsSync(dir)) return [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return [];\n }\n return entries\n .filter(isRecipeFile)\n .map((name) => ({ name, path: join(dir, name) }))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_recipe_list ─────────────────────────────────────\n server.tool(\n \"atelier_recipe_list\",\n \"List discoverable Studio Recipes — project-local <projectDir>/.atelier/recipes/*.recipe.* \" +\n \"plus ~/.atelier/recipes/*.recipe.*. Returns { name, path } entries with absolute paths.\",\n {\n projectDir: z.string().optional().describe(\"Project root to search (default: process.cwd())\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ projectDir }) => {\n const root = resolve(projectDir ?? process.cwd());\n const projectRecipes = listRecipesIn(join(root, \".atelier\", \"recipes\"));\n const userRecipes = listRecipesIn(join(homedir(), \".atelier\", \"recipes\"));\n // Project recipes take precedence; de-dupe by basename.\n const seen = new Set(projectRecipes.map((r) => r.name));\n const recipes = [...projectRecipes, ...userRecipes.filter((r) => !seen.has(r.name))];\n return ok({ count: recipes.length, recipes });\n },\n );\n\n // ── atelier_recipe_get ──────────────────────────────────────\n server.tool(\n \"atelier_recipe_get\",\n \"Load a recipe and return BOTH the parsed object and its serialized YAML text \" +\n \"(so the agent can show/explain it), plus any validation warnings.\",\n {\n path: z.string().describe(\"Recipe path or bare name (resolved like the CLI)\"),\n projectDir: z.string().optional().describe(\"Project root for name resolution (default: process.cwd())\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ path, projectDir }) => {\n const root = resolve(projectDir ?? process.cwd());\n try {\n const loaded = loadRecipe(path, root);\n return ok({\n path: loaded.path,\n recipe: loaded.recipe as unknown as Record<string, unknown>,\n yaml: recipeToYaml(loaded.recipe),\n warnings: loaded.warnings,\n });\n } catch (e) {\n return err((e as Error).message);\n }\n },\n );\n\n // ── atelier_recipe_validate ─────────────────────────────────\n server.tool(\n \"atelier_recipe_validate\",\n \"Validate a recipe from a path OR inline YAML text. Returns { success, warnings, errors }.\",\n {\n path: z.string().optional().describe(\"Recipe path or bare name to validate\"),\n yaml: z.string().optional().describe(\"Inline YAML text to validate (alternative to path)\"),\n projectDir: z.string().optional().describe(\"Project root for name resolution (default: process.cwd())\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ path, yaml, projectDir }) => {\n if (!path && yaml === undefined) {\n return err(\"Provide either `path` or `yaml` to validate\");\n }\n const root = resolve(projectDir ?? process.cwd());\n\n let parsed: unknown;\n try {\n if (yaml !== undefined) {\n parsed = parseYaml(yaml);\n } else {\n const resolved = resolveRecipePath(path as string, root);\n parsed = parseRecipeText(readFileSync(resolved, \"utf-8\"), resolved);\n }\n } catch (e) {\n return ok({ valid: false, warnings: [], errors: [{ path: \"(yaml)\", message: (e as Error).message }] });\n }\n\n const result = validateRecipe(parsed);\n if (!result.success) {\n return ok({ valid: false, warnings: [], errors: result.errors });\n }\n return ok({ valid: true, warnings: result.warnings ?? [], errors: [] });\n },\n );\n\n // ── atelier_recipe_save ─────────────────────────────────────\n server.tool(\n \"atelier_recipe_save\",\n \"Write a recipe to disk. Accepts a recipe object (serialized via YAML) OR raw YAML text. \" +\n \"Validates BEFORE writing and REFUSES to write an invalid recipe (returns an error with the \" +\n \"validation issues). Creates parent directories as needed.\",\n {\n path: z.string().describe(\"Absolute or relative file path to write the recipe to\"),\n recipe: z.record(z.unknown()).optional().describe(\"Recipe object (will be serialized to YAML)\"),\n yaml: z.string().optional().describe(\"Raw YAML text (alternative to `recipe`)\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ path, recipe, yaml }) => {\n if (recipe === undefined && yaml === undefined) {\n return err(\"Provide either `recipe` (object) or `yaml` (text) to save\");\n }\n\n // Materialize the recipe object + its YAML text.\n let parsed: unknown;\n let yamlText: string;\n if (yaml !== undefined) {\n yamlText = yaml;\n try {\n parsed = parseYaml(yaml);\n } catch (e) {\n return err(`YAML parse error: ${(e as Error).message}`);\n }\n } else {\n parsed = recipe;\n yamlText = stringifyYaml(recipe);\n }\n\n // Validate — refuse to write an invalid recipe.\n const result = validateRecipe(parsed);\n if (!result.success) {\n return err(\"Refusing to write an invalid recipe\", { errors: result.errors });\n }\n\n const absPath = resolve(path);\n try {\n mkdirSync(dirname(absPath), { recursive: true });\n writeFileSync(absPath, yamlText, \"utf-8\");\n } catch (e) {\n return err(`Failed to write recipe: ${(e as Error).message}`);\n }\n\n return ok({ path: absPath, warnings: result.warnings ?? [] });\n },\n );\n\n // ── atelier_recipe_apply ────────────────────────────────────\n server.tool(\n \"atelier_recipe_apply\",\n \"Apply a recipe's overlay_rules to an in-store document (handle + page-number overlays). \" +\n \"Accepts a recipe object OR a path/name. The result is stored back with source=\\\"llm\\\". \" +\n \"NOTE: only overlay_rules are applied here — silence-trim / transcribe / caption application \" +\n \"remain CLI-only. page_number overlays require currentIndex + totalCount; if a recipe requests \" +\n \"page_number without them, that layer is skipped and a warning is returned.\",\n {\n documentId: z.string().describe(\"In-store document ID to apply the recipe to\"),\n path: z.string().optional().describe(\"Recipe path or bare name (alternative to `recipe`)\"),\n recipe: z.record(z.unknown()).optional().describe(\"Recipe object (alternative to `path`)\"),\n projectDir: z.string().optional().describe(\"Project root for name resolution (default: process.cwd())\"),\n currentIndex: z.number().int().nonnegative().optional().describe(\"1-based carousel index for page_number\"),\n totalCount: z.number().int().positive().optional().describe(\"Total carousel size for page_number\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, path, recipe, projectDir, currentIndex, totalCount }) => {\n const result = getDoc(store, documentId);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (path === undefined && recipe === undefined) {\n return err(\"Provide either `path` or `recipe` to apply\");\n }\n\n // Resolve the recipe object (validated either way).\n let resolvedRecipe: StudioRecipe;\n if (recipe !== undefined) {\n const validated = validateRecipe(recipe);\n if (!validated.success) {\n return err(\"Invalid recipe\", { errors: validated.errors });\n }\n resolvedRecipe = validated.data;\n } else {\n const root = resolve(projectDir ?? process.cwd());\n try {\n resolvedRecipe = loadRecipe(path as string, root).recipe;\n } catch (e) {\n return err((e as Error).message);\n }\n }\n\n const { doc: updated, warnings } = applyRecipeToOverlay(doc, resolvedRecipe, {\n currentIndex,\n totalCount,\n });\n store.set(documentId, updated, \"llm\");\n\n return ok({\n documentId,\n warnings,\n layerCount: updated.layers.length,\n document: updated as unknown as Record<string, unknown>,\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Folder image ingestion tool\n//\n// Lets an agent point at a folder of images and pull them into a document as\n// registered assets + (optionally) fit-to-canvas ImageVisual layers.\n//\n// The layer-building + background-swap convention mirrors\n// @a-company/atelier-studio's image-drop helper (createImageLayerFromFile /\n// buildImageLayer), adapted from the browser File/dataURL path to a node\n// filesystem path. MCP does not depend on the studio package, so the logic is\n// duplicated here (same pattern as the recipe-tool / overlay duplication\n// elsewhere in this package). Aspect-fit (fitImageToCanvas) is intentionally\n// NOT reused here — see the dimension note below.\n//\n// Dimension note: we do NOT add an image-dimension dependency. Without natural\n// dimensions we cannot compute true aspect-fit, so each layer's bounds default\n// to a centered square of min(canvas.width, canvas.height). This is surfaced in\n// the tool description and in the response `note`.\n\nimport { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { resolve, join, basename, extname } from \"node:path\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Layer } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nconst IMAGE_EXTS = new Set([\".png\", \".jpg\", \".jpeg\", \".webp\", \".gif\", \".svg\"]);\n\nfunction isImageFile(name: string): boolean {\n return IMAGE_EXTS.has(extname(name).toLowerCase());\n}\n\n/**\n * Minimal substring/`*`-glob match. Supports a single-segment glob (no path\n * separators) with `*` wildcards — enough for \"*.png\" / \"hero-*\". Returns true\n * for an undefined/empty pattern (match-all).\n */\nfunction matchesGlob(name: string, glob: string | undefined): boolean {\n if (!glob) return true;\n // Translate the glob to a RegExp: escape regex specials, then * → .*\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\*/g, \".*\").replace(/\\?/g, \".\");\n return new RegExp(`^${escaped}$`, \"i\").test(name);\n}\n\n/**\n * Derive a stable, filesystem-safe assetId from a filename, de-duped against a\n * set of already-used ids. \"hero shot.png\" → \"hero-shot\", colliding → \"-2\".\n */\nfunction deriveAssetId(filename: string, used: Set<string>): string {\n const stem = basename(filename, extname(filename));\n const base = stem\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"image\";\n let candidate = base;\n let n = 2;\n while (used.has(candidate)) {\n candidate = `${base}-${n}`;\n n++;\n }\n used.add(candidate);\n return candidate;\n}\n\n/** Pick a unique layer id `${prefix}-N` not colliding with existing layers. */\nfunction nextImageLayerId(existing: Set<string>, seq: number): string {\n let candidate = `image-${seq}`;\n let n = seq;\n while (existing.has(candidate)) {\n n++;\n candidate = `image-${n}`;\n }\n existing.add(candidate);\n return candidate;\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_import_images ───────────────────────────────────\n server.tool(\n \"atelier_import_images\",\n \"Import every image in a folder into a document. Registers each as an asset and, \" +\n \"unless asLayers is false, creates one fit-to-canvas ImageVisual layer per image \" +\n \"(centered). Extensions: .png .jpg .jpeg .webp .gif .svg. Optional glob filters by \" +\n \"filename (e.g. \\\"*.png\\\"); results are sorted by name. If the folder has exactly one \" +\n \"image AND the doc's layer[0] is the welcome \\\"background\\\" placeholder, that image \" +\n \"replaces the placeholder in place. Asset src is the absolute file path. \" +\n \"Layer bounds default to a centered min(canvas.w, canvas.h) square because natural \" +\n \"image dimensions are not measured (no image-dimension dependency).\",\n {\n documentId: z.string().describe(\"In-store document ID to import into\"),\n dir: z.string().describe(\"Directory containing the images\"),\n glob: z.string().optional().describe(\"Optional filename glob, e.g. \\\"*.png\\\" (default: all images)\"),\n asLayers: z.boolean().optional().describe(\"Create layers per image (default: true). false = register assets only.\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, dir, glob, asLayers }) => {\n const result = getDoc(store, documentId);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const absDir = resolve(dir);\n if (!existsSync(absDir)) return err(`Directory \"${absDir}\" does not exist`);\n if (!statSync(absDir).isDirectory()) return err(`Path \"${absDir}\" is not a directory`);\n\n const files = readdirSync(absDir)\n .filter((name) => isImageFile(name) && matchesGlob(name, glob))\n .sort((a, b) => a.localeCompare(b));\n\n if (files.length === 0) {\n return err(`No image files matched in \"${absDir}\"${glob ? ` (glob: ${glob})` : \"\"}`);\n }\n\n const makeLayers = asLayers !== false;\n const canvas = doc.canvas;\n const square = Math.min(canvas.width, canvas.height);\n\n // Background-swap is only allowed for a single-image import (mirrors the\n // welcome-placeholder convention from the Studio image-drop helper).\n const allowBackgroundSwap = files.length === 1 && doc.layers[0]?.id === \"background\";\n\n // Copy-on-write: build a NEW doc with cloned assets + layers and store it\n // once at the end (mirrors applyRecipeToOverlay). A concurrent onChange\n // reader (the studio bridge) must never observe a half-mutated document.\n const newAssets: NonNullable<AtelierDocument[\"assets\"]> = { ...(doc.assets ?? {}) };\n const newLayers: Layer[] = [...doc.layers];\n\n const usedAssetIds = new Set(Object.keys(newAssets));\n const existingLayerIds = new Set(newLayers.map((l) => l.id));\n\n const assetIds: string[] = [];\n const layerIds: string[] = [];\n\n let layerSeq = newLayers.length + 1;\n for (const file of files) {\n const absPath = join(absDir, file);\n const assetId = deriveAssetId(file, usedAssetIds);\n newAssets[assetId] = { type: \"image\", src: absPath, description: file };\n assetIds.push(assetId);\n\n if (!makeLayers) continue;\n\n const layerId = nextImageLayerId(existingLayerIds, layerSeq);\n layerSeq++;\n\n const layer: Layer = {\n id: layerId,\n visual: { type: \"image\", assetId, src: absPath },\n frame: { x: canvas.width / 2, y: canvas.height / 2 },\n bounds: { width: square, height: square },\n anchorPoint: { x: 0.5, y: 0.5 },\n opacity: 1,\n };\n\n if (allowBackgroundSwap) {\n // Single image filling the welcome placeholder — swap in place so any\n // existing overlays stay on top.\n newLayers[0] = layer;\n } else {\n // Bottom of the z-stack (renderer paints index 0 first), behind\n // existing overlays — matches the Studio drop convention.\n newLayers.unshift(layer);\n }\n layerIds.push(layerId);\n }\n\n const newDoc: AtelierDocument = { ...doc, assets: newAssets, layers: newLayers };\n store.set(documentId, newDoc, \"llm\");\n\n return ok({\n imported: files.length,\n assetIds,\n layerIds,\n asLayers: makeLayers,\n note:\n \"Layer bounds default to a centered square (min canvas dimension) — \" +\n \"natural image dimensions are not measured.\",\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Bridge protocol (LLM↔human live-mutation envelopes)\n//\n// Shared envelope types for the WebSocket bridge that connects an external\n// MCP client (e.g. Claude Desktop running with `atelier-mcp`) to the\n// browser-side AtelierStudio running inside `atelier studio`.\n//\n// The mutation loop is:\n//\n// LLM tool call ──► MCP server ──► DocumentStore.set(source:\"llm\")\n// │\n// ▼\n// DocumentStore.onChange fires\n// │\n// ▼\n// WS bridge broadcasts `llm:mutation`\n// │\n// ▼\n// Browser studio.applyMutation(op)\n// │\n// ▼\n// Canvas re-renders + toast attribution\n// (Cmd-Z still works — history snapshot)\n//\n// Human edit ──► browser AtelierStudio\n// │\n// ▼\n// onDocumentChange ──► `doc:patch` envelope\n// │\n// ▼\n// WS bridge writes DocumentStore.set(source:\"human\")\n// │\n// ▼\n// onChange filter SKIPS broadcast\n// (otherwise the browser would echo itself)\n//\n// v1 ships whole-document replacement so the envelope stays trivial.\n// JSON-patch op shape is v1.1 once we measure the byte cost on real docs.\n\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\n\n/**\n * Who triggered a mutation. Mirrors `DocumentStore.MutationSource` so the\n * tag travels end-to-end without translation between the server-side\n * store and the browser-side Studio.\n */\nexport type MutationSource = \"human\" | \"llm\" | \"system\";\n\n/** Wire-format protocol version. Bump on any breaking envelope change. */\nexport const BRIDGE_PROTOCOL_VERSION = 1 as const;\n\n/**\n * Server-sent on each new bridge client connection. Carries a generated\n * client id and the negotiated protocol version. The client uses this to\n * detect mismatched bridge versions.\n */\nexport interface HelloEnvelope {\n type: \"hello\";\n clientId: string;\n protocolVersion: typeof BRIDGE_PROTOCOL_VERSION;\n}\n\n/**\n * Client → server explicit load request. v1 sends `doc:loaded` proactively\n * on connect so this is reserved for future multi-doc sessions; included\n * now to lock the envelope shape.\n */\nexport interface DocLoadEnvelope {\n type: \"doc:load\";\n documentId: string;\n}\n\n/**\n * Server → client: here is the current state of the document.\n * Sent on connect (after `hello`) and on document switch.\n */\nexport interface DocLoadedEnvelope {\n type: \"doc:loaded\";\n documentId: string;\n doc: AtelierDocument;\n}\n\n/**\n * Client → server: I (the human) just made an edit. The server writes this\n * into the DocumentStore with `source:\"human\"` so the onChange filter does\n * NOT echo it back as `llm:mutation`.\n */\nexport interface DocPatchEnvelope {\n type: \"doc:patch\";\n documentId: string;\n doc: AtelierDocument;\n source: MutationSource;\n /** Optional correlation id so the client can match an ack/error response. */\n opId?: string;\n}\n\n/**\n * Server → client: an LLM (or system source) mutated the document.\n * The browser translates this to `studio.applyMutation({type:\"doc:replace\", doc, source})`.\n */\nexport interface LlmMutationEnvelope {\n type: \"llm:mutation\";\n documentId: string;\n doc: AtelierDocument;\n source: MutationSource;\n /** Name of the MCP tool that triggered the mutation, when known. */\n toolName?: string;\n /** Optional correlation id (mirrors any client-side request id). */\n opId?: string;\n}\n\n/** Generic error envelope, in either direction. */\nexport interface ErrorEnvelope {\n type: \"error\";\n code: string;\n message: string;\n opId?: string;\n}\n\n/** Discriminated union of all envelopes carried over the bridge. */\nexport type BridgeEnvelope =\n | HelloEnvelope\n | DocLoadEnvelope\n | DocLoadedEnvelope\n | DocPatchEnvelope\n | LlmMutationEnvelope\n | ErrorEnvelope;\n\n/** Type guard for runtime envelope validation. */\nexport function isBridgeEnvelope(value: unknown): value is BridgeEnvelope {\n if (!value || typeof value !== \"object\") return false;\n const t = (value as { type?: unknown }).type;\n return (\n t === \"hello\" ||\n t === \"doc:load\" ||\n t === \"doc:loaded\" ||\n t === \"doc:patch\" ||\n t === \"llm:mutation\" ||\n t === \"error\"\n );\n}\n","// @a-company/atelier-mcp — WebSocket server transport for the MCP SDK\n//\n// Wraps a single WebSocket (from the `ws` library) as an MCP Transport so\n// the same `McpServer` from `createServer()` can be reached over `/mcp` on\n// the `atelier studio` Hono-equivalent (Vite-backed) HTTP server.\n//\n// Used in tandem with the live bridge in `bridge-protocol.ts`:\n// - MCP over /mcp → external client drives DocumentStore mutations.\n// - Bridge over /bridge → broadcasts those mutations into the browser\n// studio so the human sees them land in real time.\n//\n// Per-connection instance: one transport per WebSocket. The CLI spawns a\n// new `McpServer` per connection but shares the underlying `DocumentStore`\n// across all of them so mutations from any client surface through the\n// single onChange emitter the bridge subscribes to.\n\nimport type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { WebSocket as WsWebSocket } from \"ws\";\n\n/** Minimal slice of `ws.WebSocket` we depend on — keeps the transport mockable. */\nexport interface WsLike {\n readyState: number;\n send(data: string): void;\n close(): void;\n on(event: \"message\", listener: (data: unknown) => void): void;\n on(event: \"close\", listener: () => void): void;\n on(event: \"error\", listener: (err: Error) => void): void;\n off?(event: string, listener: (...args: unknown[]) => void): void;\n}\n\n/**\n * MCP server transport over a single WebSocket connection.\n *\n * Lifecycle:\n * 1. CLI accepts WS upgrade, instantiates `new WebSocketServerTransport(ws)`.\n * 2. CLI passes it to `server.connect(transport)` — the SDK then calls\n * `start()` and wires `onmessage` / `send()`.\n * 3. Incoming WS frames → parsed as JSON-RPC → `onmessage(message)`.\n * 4. SDK `send(message)` → JSON.stringify → `ws.send(...)`.\n * 5. WS `close` → `onclose()` fires once.\n *\n * Parse errors on inbound frames are surfaced via `onerror()` but do NOT\n * close the connection — a malformed message from a misbehaving client\n * should not knock out a healthy session.\n */\nexport class WebSocketServerTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n sessionId?: string;\n\n private started = false;\n private closed = false;\n\n constructor(private readonly ws: WsLike) {}\n\n async start(): Promise<void> {\n if (this.started) {\n throw new Error(\n \"WebSocketServerTransport already started — the MCP SDK calls start() automatically; do not call it again\",\n );\n }\n this.started = true;\n\n this.ws.on(\"message\", (data: unknown) => {\n // `ws` delivers Buffer / ArrayBuffer / Buffer[] depending on frame type.\n // Normalize to string before JSON.parse.\n let text: string;\n try {\n if (typeof data === \"string\") {\n text = data;\n } else if (data instanceof Buffer) {\n text = data.toString(\"utf-8\");\n } else if (Array.isArray(data)) {\n text = Buffer.concat(data as Buffer[]).toString(\"utf-8\");\n } else if (data instanceof ArrayBuffer) {\n text = Buffer.from(data).toString(\"utf-8\");\n } else {\n text = String(data);\n }\n } catch (err) {\n this.onerror?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch (err) {\n this.onerror?.(\n new Error(\n `WebSocketServerTransport: failed to parse JSON-RPC message: ${\n err instanceof Error ? err.message : String(err)\n }`,\n ),\n );\n return;\n }\n\n // The SDK validates message shape downstream; we just hand it the parsed value.\n this.onmessage?.(parsed as JSONRPCMessage);\n });\n\n this.ws.on(\"close\", () => {\n if (this.closed) return;\n this.closed = true;\n this.onclose?.();\n });\n\n this.ws.on(\"error\", (err: Error) => {\n this.onerror?.(err);\n });\n }\n\n async send(message: JSONRPCMessage): Promise<void> {\n if (this.closed) {\n throw new Error(\"WebSocketServerTransport: cannot send after close\");\n }\n // ws.WebSocket.OPEN === 1. Hard-coded to avoid importing ws at top level\n // (keeps the test seam clean — WsLike can be a plain object with readyState).\n if (this.ws.readyState !== 1) {\n throw new Error(\n `WebSocketServerTransport: WebSocket is not OPEN (readyState=${this.ws.readyState})`,\n );\n }\n this.ws.send(JSON.stringify(message));\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n try {\n this.ws.close();\n } catch {\n // Swallow — close() should be idempotent and never throw.\n }\n this.onclose?.();\n }\n}\n\n/** Re-export the imported `ws.WebSocket` type for downstream consumers. */\nexport type { WsWebSocket };\n"],"mappings":"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","names":["z","z","err","z","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","z","getDoc","ok","err","AnimatablePropertyEnum","EasingInputSchema","PresetDeltaSchema","z","register","z","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","getDoc","ok","err","EasingInputSchema","register","z","colorToCSS","r","g","b","a","isExpression","kfs","buildTransform","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","getDoc","ok","err","DEFAULT_OVERLAY_MARGIN","anchorToFrame","renderPageNumberFormat","register","z","existsSync","readdirSync","resolve","join","z","getDoc","ok","err","register","err","register"]}
1
+ {"version":3,"sources":["../../mcp/src/index.ts","../../mcp/src/store.ts","../../mcp/src/tools/document.ts","../../schema/src/units.ts","../../schema/src/coordinates.ts","../../schema/src/color.ts","../../schema/src/shape.ts","../../schema/src/easing.ts","../../schema/src/shadow.ts","../../schema/src/layer.ts","../../schema/src/interaction.ts","../../schema/src/delta.ts","../../schema/src/state.ts","../../schema/src/preset.ts","../../schema/src/variable.ts","../../schema/src/asset.ts","../../schema/src/document.ts","../../schema/src/timeline.ts","../../schema/src/slides.ts","../../schema/src/design.ts","../../schema/src/recipe.ts","../../schema/src/validate.ts","../../schema/src/parse.ts","../../schema/src/artifacts/slot.ts","../../schema/src/artifacts/technique.ts","../../schema/src/artifacts/design.ts","../../schema/src/artifacts/script.ts","../../schema/src/artifacts/storyboard.ts","../../schema/src/artifacts/parse.ts","../../schema/src/artifacts/validate.ts","../../schema/src/workspace.ts","../../schema/src/media-notes.ts","../../mcp/src/tools/layers.ts","../../mcp/src/tools/shapes.ts","../../mcp/src/tools/states.ts","../../mcp/src/tools/deltas.ts","../../math/src/easing.ts","../../math/src/spring.ts","../../math/src/lerp.ts","../../math/src/color.ts","../../math/src/path.ts","../../core/src/resolver/delta-resolver.ts","../../core/src/resolver/easing-resolver.ts","../../core/src/expressions/expression-evaluator.ts","../../core/src/resolver/frame-resolver.ts","../../core/src/validation/overlap-validator.ts","../../core/src/builder/document-builder.ts","../../core/src/units/resolve-units.ts","../../core/src/presets/preset-resolver.ts","../../core/src/state/state-machine.ts","../../core/src/templates/template-resolver.ts","../../core/src/audio/audio-timing.ts","../../mcp/src/tools/presets.ts","../../mcp/src/tools/preview.ts","../../mcp/src/tools/templates.ts","../../mcp/src/tools/layer-effects.ts","../../mcp/src/tools/state-config.ts","../../mcp/src/tools/export.ts","../../canvas/src/styles.ts","../../canvas/src/apply-properties.ts","../../canvas/src/renderers/shape-renderer.ts","../../canvas/src/renderers/text-renderer.ts","../../canvas/src/renderers/image-renderer.ts","../../canvas/src/renderers/video-renderer.ts","../../canvas/src/renderers/ref-renderer.ts","../../canvas/src/render-frame.ts","../../canvas/src/image-cache.ts","../../svg/src/render-svg.ts","../../svg/src/svg-properties.ts","../../svg/src/svg-gradients.ts","../../svg/src/svg-shapes.ts","../../svg/src/svg-text.ts","../../svg/src/svg-filters.ts","../../svg/src/svg-clip.ts","../../lottie/src/map-colors.ts","../../lottie/src/map-shapes.ts","../../lottie/src/map-easing.ts","../../lottie/src/map-keyframes.ts","../../lottie/src/map-layers.ts","../../lottie/src/warnings.ts","../../lottie/src/export-lottie.ts","../../mcp/src/tools/assets.ts","../../mcp/src/tools/variables.ts","../../mcp/src/tools/interactions.ts","../../mcp/src/tools/refs.ts","../../mcp/src/tools/performance.ts","../../mcp/src/tools/overlays.ts","../../mcp/src/tools/recipes.ts","../../mcp/src/tools/import-images.ts","../../mcp/src/tools/mind-map.ts","../../mcp/src/tools/effective-transcript.ts","../../mcp/src/tools/media-notes.ts","../../mcp/src/tools/clips.ts","../../mcp/src/lib/timeline-ops.ts","../../mcp/src/tools/rename-media.ts","../../mcp/src/lib/rename-media.ts","../../mcp/src/tools/docs.ts","../../mcp/src/lib/doc-management.ts","../../mcp/src/lib/doc-management-types.ts","../../mcp/src/bridge-protocol.ts","../../mcp/src/transports/ws-transport.ts"],"sourcesContent":["// @a-company/atelier-mcp — MCP server: AI authoring interface for animations\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { DocumentStore } from \"./store.js\";\nimport { register as registerDocumentTools } from \"./tools/document.js\";\nimport { register as registerLayerTools } from \"./tools/layers.js\";\nimport { register as registerShapeTools } from \"./tools/shapes.js\";\nimport { register as registerStateTools } from \"./tools/states.js\";\nimport { register as registerDeltaTools } from \"./tools/deltas.js\";\nimport { register as registerPresetTools } from \"./tools/presets.js\";\nimport { register as registerPreviewTools } from \"./tools/preview.js\";\nimport { register as registerTemplateTools } from \"./tools/templates.js\";\nimport { register as registerLayerEffectTools } from \"./tools/layer-effects.js\";\nimport { register as registerStateConfigTools } from \"./tools/state-config.js\";\nimport { register as registerExportTools } from \"./tools/export.js\";\nimport { register as registerAssetTools } from \"./tools/assets.js\";\nimport { register as registerVariableTools } from \"./tools/variables.js\";\nimport { register as registerInteractionTools } from \"./tools/interactions.js\";\nimport { register as registerRefTools } from \"./tools/refs.js\";\nimport { register as registerPerformanceTools } from \"./tools/performance.js\";\nimport { register as registerOverlayTools } from \"./tools/overlays.js\";\nimport { register as registerRecipeTools } from \"./tools/recipes.js\";\nimport { register as registerImportImageTools } from \"./tools/import-images.js\";\nimport { register as registerMindMapTools } from \"./tools/mind-map.js\";\nimport { register as registerEffectiveTranscriptTools } from \"./tools/effective-transcript.js\";\nimport { register as registerMediaNotesTools } from \"./tools/media-notes.js\";\n// ── v1.0 clip tools ──────\nimport { register as registerClipTools } from \"./tools/clips.js\";\n// ── v1.0 rename-media tool ──────\nimport { register as registerRenameMediaTool } from \"./tools/rename-media.js\";\n// ── v1.0.x doc tools ──────\nimport { register as registerDocTools } from \"./tools/docs.js\";\n\nexport { DocumentStore } from \"./store.js\";\nexport type { MutationSource, ChangeListener } from \"./store.js\";\nexport {\n BRIDGE_PROTOCOL_VERSION,\n isBridgeEnvelope,\n} from \"./bridge-protocol.js\";\nexport type {\n BridgeEnvelope,\n HelloEnvelope,\n DocLoadEnvelope,\n DocLoadedEnvelope,\n DocPatchEnvelope,\n LlmMutationEnvelope,\n ErrorEnvelope,\n MediaListChangedEnvelope,\n TranscriptAddedEnvelope,\n MediaIngestProgressEnvelope,\n FileDeletedEnvelope,\n MediaDeletedEnvelope,\n ProjectDeletedEnvelope,\n} from \"./bridge-protocol.js\";\nexport { WebSocketServerTransport } from \"./transports/ws-transport.js\";\nexport type { WsLike } from \"./transports/ws-transport.js\";\nexport { register as registerDocumentTools } from \"./tools/document.js\";\nexport { register as registerLayerTools } from \"./tools/layers.js\";\nexport { register as registerShapeTools } from \"./tools/shapes.js\";\nexport { register as registerStateTools } from \"./tools/states.js\";\nexport { register as registerDeltaTools } from \"./tools/deltas.js\";\nexport { register as registerPresetTools } from \"./tools/presets.js\";\nexport { register as registerPreviewTools } from \"./tools/preview.js\";\nexport { register as registerTemplateTools } from \"./tools/templates.js\";\nexport { register as registerLayerEffectTools } from \"./tools/layer-effects.js\";\nexport { register as registerStateConfigTools } from \"./tools/state-config.js\";\nexport { register as registerExportTools } from \"./tools/export.js\";\nexport { register as registerAssetTools } from \"./tools/assets.js\";\nexport { register as registerVariableTools } from \"./tools/variables.js\";\nexport { register as registerInteractionTools } from \"./tools/interactions.js\";\nexport { register as registerRefTools } from \"./tools/refs.js\";\nexport { register as registerPerformanceTools } from \"./tools/performance.js\";\nexport { register as registerOverlayTools } from \"./tools/overlays.js\";\nexport { register as registerRecipeTools } from \"./tools/recipes.js\";\nexport { register as registerImportImageTools } from \"./tools/import-images.js\";\nexport { register as registerMindMapTools } from \"./tools/mind-map.js\";\n// ── v1.0 clip tools ──────\nexport {\n register as registerClipTools,\n __setTranscribeClipFn,\n __setProbeDurationFn,\n type TranscribeClipFn,\n} from \"./tools/clips.js\";\n// ── v1.0 rename-media tool ──────\nexport { register as registerRenameMediaTool } from \"./tools/rename-media.js\";\n// ── v1.0.x doc tools ──────\nexport { register as registerDocTools } from \"./tools/docs.js\";\n\n/**\n * Create a fully configured MCP server with all Atelier tools registered.\n * Returns both the server and the backing store for testing.\n *\n * The `store` parameter is optional — pass an existing `DocumentStore` to\n * share state across multiple MCP server instances. This is how the\n * `atelier studio` command's per-connection WebSocket MCP servers all\n * surface their writes through a single `onChange` emitter that the live\n * bridge subscribes to (task #10).\n */\nexport function createServer(\n store: DocumentStore = new DocumentStore(),\n): { server: McpServer; store: DocumentStore } {\n\n const server = new McpServer(\n { name: \"atelier\", version: \"0.1.0\" },\n { capabilities: { tools: {} } },\n );\n\n registerDocumentTools(server, store);\n registerLayerTools(server, store);\n registerShapeTools(server, store);\n registerStateTools(server, store);\n registerDeltaTools(server, store);\n registerPresetTools(server, store);\n registerPreviewTools(server, store);\n registerTemplateTools(server, store);\n registerLayerEffectTools(server, store);\n registerStateConfigTools(server, store);\n registerExportTools(server, store);\n registerAssetTools(server, store);\n registerVariableTools(server, store);\n registerInteractionTools(server, store);\n registerRefTools(server, store);\n registerPerformanceTools(server, store);\n registerOverlayTools(server, store);\n registerRecipeTools(server, store);\n registerImportImageTools(server, store);\n registerMindMapTools(server, store);\n registerEffectiveTranscriptTools(server, store);\n registerMediaNotesTools(server, store);\n // ── v1.0 clip tools ──────\n registerClipTools(server, store);\n // ── v1.0 rename-media tool ──────\n registerRenameMediaTool(server, store);\n // ── v1.0.x doc tools ──────\n registerDocTools(server, store);\n\n return { server, store };\n}\n\n// ── Main entry point ─────────────────────────────────────────\n// When run directly, connect via stdio transport.\nconst isMain =\n typeof process !== \"undefined\" &&\n process.argv[1] &&\n (process.argv[1].endsWith(\"/index.js\") ||\n process.argv[1].endsWith(\"/index.cjs\") ||\n process.argv[1].includes(\"atelier-mcp\"));\n\nif (isMain) {\n const { server } = createServer();\n const transport = new StdioServerTransport();\n server.connect(transport).catch((error) => {\n console.error(\"Failed to start Atelier MCP server:\", error);\n process.exit(1);\n });\n}\n","// @a-company/atelier-mcp — In-memory document store\n\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\n\nlet counter = 0;\n\nfunction generateId(): string {\n counter++;\n return `doc_${Date.now()}_${counter}`;\n}\n\n/**\n * Source of a mutation — distinguishes who triggered the change so listeners\n * (notably the live WS bridge in task #10) can avoid echoing changes back to\n * the originator and creating a feedback loop.\n */\nexport type MutationSource = \"human\" | \"llm\" | \"system\";\n\n/**\n * Listener invoked after every mutating store operation.\n *\n * @param id The document ID that changed.\n * @param doc The new document value, or `null` if the document was deleted.\n * @param source Who triggered the change. Defaults to \"system\" when the caller\n * did not tag the mutation.\n */\nexport type ChangeListener = (\n id: string,\n doc: AtelierDocument | null,\n source: MutationSource,\n) => void;\n\n/**\n * In-memory store for AtelierDocuments.\n * Each document is keyed by a string ID.\n *\n * Supports an `onChange` event-emitter API so external observers (e.g. the\n * forthcoming WS bridge for the LLM↔human live-mutation loop — see task #10)\n * can subscribe to mutations and ferry them to other processes.\n */\nexport class DocumentStore {\n private docs = new Map<string, AtelierDocument>();\n private listeners: ChangeListener[] = [];\n\n /** Create a new document entry. Returns the assigned ID. */\n create(doc: AtelierDocument, id?: string, source: MutationSource = \"system\"): string {\n const docId = id ?? generateId();\n if (this.docs.has(docId)) {\n throw new Error(`Document \"${docId}\" already exists`);\n }\n this.docs.set(docId, doc);\n this.emit(docId, doc, source);\n return docId;\n }\n\n /** Get a document by ID. */\n get(id: string): AtelierDocument | undefined {\n return this.docs.get(id);\n }\n\n /** Set (overwrite) a document by ID. */\n set(id: string, doc: AtelierDocument, source: MutationSource = \"system\"): void {\n this.docs.set(id, doc);\n this.emit(id, doc, source);\n }\n\n /** Delete a document by ID. Returns true if it existed. */\n delete(id: string, source: MutationSource = \"system\"): boolean {\n const existed = this.docs.delete(id);\n if (existed) this.emit(id, null, source);\n return existed;\n }\n\n /** Check if a document exists. */\n has(id: string): boolean {\n return this.docs.has(id);\n }\n\n /** List all document IDs and their names. */\n list(): Array<{ id: string; name: string; canvas: AtelierDocument[\"canvas\"] }> {\n const result: Array<{ id: string; name: string; canvas: AtelierDocument[\"canvas\"] }> = [];\n for (const [id, doc] of this.docs) {\n result.push({ id, name: doc.name, canvas: doc.canvas });\n }\n return result;\n }\n\n /** Clear all documents (useful for testing). Does NOT fire onChange. */\n clear(): void {\n this.docs.clear();\n }\n\n /**\n * Subscribe to mutation events. The listener is invoked after every\n * create()/set()/delete() with the changed document ID, the new value\n * (or `null` when deleted), and the source tag.\n *\n * Returns an unsubscribe function. Multiple listeners are supported and\n * delivered in registration order. A listener that throws is isolated —\n * the error is swallowed and remaining listeners still fire.\n *\n * TODO(#10): the live WS bridge will subscribe here to forward LLM-side\n * mutations into the in-browser Studio (which exposes the symmetric\n * `AtelierStudio.applyMutation()` API).\n */\n onChange(listener: ChangeListener): () => void {\n this.listeners.push(listener);\n return () => {\n const idx = this.listeners.indexOf(listener);\n if (idx !== -1) this.listeners.splice(idx, 1);\n };\n }\n\n private emit(id: string, doc: AtelierDocument | null, source: MutationSource): void {\n // Snapshot the list so a listener mutating subscriptions mid-emit doesn't\n // skip or double-fire siblings.\n const snapshot = this.listeners.slice();\n for (const listener of snapshot) {\n try {\n listener(id, doc, source);\n } catch {\n // Isolate listener failures — one buggy subscriber must not break the\n // mutation chain for the rest. No logger is wired into this package\n // today; if/when one lands, surface the error here.\n }\n }\n }\n}\n","// @a-company/atelier-mcp — Document management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { validateDocument, parseAtelier, serializeAtelier } from \"@a-company/atelier-schema\";\nimport type { DocumentStore } from \"../store.js\";\n\n/** Helper: get document or return error result */\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_create ──────────────────────────────────────────\n server.tool(\n \"atelier_create\",\n \"Create a new Atelier animation document with canvas settings\",\n {\n name: z.string().describe(\"Animation name\"),\n width: z.number().positive().describe(\"Canvas width in pixels\"),\n height: z.number().positive().describe(\"Canvas height in pixels\"),\n fps: z.number().positive().int().describe(\"Frames per second\"),\n background: z.string().optional().describe(\"Background color (hex string)\"),\n description: z.string().optional().describe(\"Animation description\"),\n tags: z.array(z.string()).optional().describe(\"Tags for categorization\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ name, width, height, fps, background, description, tags }) => {\n const doc: AtelierDocument = {\n version: \"1.0\",\n name,\n canvas: { width, height, fps, ...(background ? { background } : {}) },\n layers: [],\n states: {},\n ...(description ? { description } : {}),\n ...(tags ? { tags } : {}),\n };\n\n const validation = validateDocument(doc);\n if (!validation.success) {\n return err(`Validation failed: ${validation.errors.map(e => `${e.path}: ${e.message}`).join(\"; \")}`);\n }\n\n const id = store.create(doc);\n return ok({ id, name: doc.name, canvas: doc.canvas });\n },\n );\n\n // ── atelier_info ────────────────────────────────────────────\n server.tool(\n \"atelier_info\",\n \"Get summary information about an Atelier document\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const stateNames = Object.keys(doc.states);\n const totalDuration = stateNames.reduce(\n (sum, name) => sum + doc.states[name].duration,\n 0,\n );\n\n return ok({\n name: doc.name,\n description: doc.description,\n tags: doc.tags,\n canvas: doc.canvas,\n layerCount: doc.layers.length,\n stateNames,\n totalDuration,\n presetNames: doc.presets ? Object.keys(doc.presets) : [],\n });\n },\n );\n\n // ── atelier_load ────────────────────────────────────────────\n server.tool(\n \"atelier_load\",\n \"Load an Atelier document from a YAML string\",\n {\n id: z.string().optional().describe(\"Custom document ID (auto-generated if omitted)\"),\n yaml: z.string().describe(\"YAML string representing an Atelier document\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, yaml }) => {\n const parsed = parseAtelier(yaml);\n if (!parsed.success) {\n return err(`Parse/validation failed: ${parsed.errors.map(e => `${e.path}: ${e.message}`).join(\"; \")}`);\n }\n\n const docId = store.create(parsed.data, id);\n return ok({ id: docId, name: parsed.data.name });\n },\n );\n\n // ── atelier_export ──────────────────────────────────────────\n server.tool(\n \"atelier_export\",\n \"Export an Atelier document as a YAML string\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n\n const yaml = serializeAtelier(result.doc);\n return { content: [{ type: \"text\" as const, text: yaml }] };\n },\n );\n\n // ── atelier_list ────────────────────────────────────────────\n server.tool(\n \"atelier_list\",\n \"List all Atelier documents in the store\",\n {},\n { readOnlyHint: true, destructiveHint: false },\n async () => {\n const docs = store.list();\n return ok({ documents: docs, count: docs.length });\n },\n );\n}\n","import { z } from \"zod\";\n\n/** Pixel value — any number */\nexport const PixelSchema = z.number();\n\n/** Percentage string like \"50%\" */\nexport const PercentageSchema = z.string().regex(/^-?\\d+(\\.\\d+)?%$/, {\n message: \"Percentage must be a number followed by %, e.g. \\\"50%\\\"\",\n});\n\n/** Either pixel or percentage */\nexport const UnitValueSchema = z.union([PixelSchema, PercentageSchema]);\n","import { z } from \"zod\";\nimport { UnitValueSchema } from \"./units.js\";\n\nexport const FrameSchema = z.object({\n x: UnitValueSchema,\n y: UnitValueSchema,\n});\n\nexport const BoundsSchema = z.object({\n width: UnitValueSchema,\n height: UnitValueSchema,\n});\n\nexport const AnchorPointSchema = z.object({\n x: z.number().min(0).max(1),\n y: z.number().min(0).max(1),\n});\n","import { z } from \"zod\";\n\nexport const RGBAColorSchema = z.object({\n r: z.number().min(0).max(255),\n g: z.number().min(0).max(255),\n b: z.number().min(0).max(255),\n a: z.number().min(0).max(1),\n});\n\nexport const HSLAColorSchema = z.object({\n h: z.number().min(0).max(360),\n s: z.number().min(0).max(100),\n l: z.number().min(0).max(100),\n a: z.number().min(0).max(1),\n});\n\nexport const HexColorSchema = z.string().regex(/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/, {\n message: \"Color must be a hex string: #RGB, #RGBA, #RRGGBB, or #RRGGBBAA\",\n});\n\nexport const ColorSchema = z.union([RGBAColorSchema, HSLAColorSchema, HexColorSchema]);\n","import { z } from \"zod\";\nimport { ColorSchema } from \"./color.js\";\nimport { UnitValueSchema } from \"./units.js\";\n\nexport const PathPointSchema = z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n});\n\nexport const RectShapeSchema = z.object({\n type: z.literal(\"rect\"),\n cornerRadius: z.union([\n z.number().min(0),\n z.tuple([z.number().min(0), z.number().min(0), z.number().min(0), z.number().min(0)]),\n ]).optional(),\n});\n\nexport const EllipseShapeSchema = z.object({\n type: z.literal(\"ellipse\"),\n});\n\nexport const PathShapeSchema = z.object({\n type: z.literal(\"path\"),\n points: z.array(PathPointSchema).min(2, \"Path must have at least 2 points\"),\n closed: z.boolean().optional(),\n});\n\nexport const ShapeSchema = z.discriminatedUnion(\"type\", [\n RectShapeSchema,\n EllipseShapeSchema,\n PathShapeSchema,\n]);\n\nexport const GradientStopSchema = z.object({\n offset: z.number().min(0).max(1),\n color: ColorSchema,\n});\n\nexport const SolidFillSchema = z.object({\n type: z.literal(\"solid\"),\n color: ColorSchema,\n});\n\nexport const LinearGradientFillSchema = z.object({\n type: z.literal(\"linear-gradient\"),\n angle: z.number(),\n stops: z.array(GradientStopSchema).min(2, \"Gradient needs at least 2 stops\"),\n});\n\nexport const RadialGradientFillSchema = z.object({\n type: z.literal(\"radial-gradient\"),\n center: z.object({ x: UnitValueSchema, y: UnitValueSchema }),\n radius: UnitValueSchema,\n stops: z.array(GradientStopSchema).min(2, \"Gradient needs at least 2 stops\"),\n});\n\nexport const FillSchema = z.discriminatedUnion(\"type\", [\n SolidFillSchema,\n LinearGradientFillSchema,\n RadialGradientFillSchema,\n]);\n\nexport const StrokeSchema = z.object({\n color: ColorSchema,\n width: z.number().min(0),\n dash: z.array(z.number().min(0)).optional(),\n lineCap: z.enum([\"butt\", \"round\", \"square\"]).optional(),\n lineJoin: z.enum([\"miter\", \"round\", \"bevel\"]).optional(),\n strokeStart: z.number().min(0).max(1).optional(),\n strokeEnd: z.number().min(0).max(1).optional(),\n});\n\nexport const TextStyleSchema = z.object({\n fontFamily: z.string().min(1, \"fontFamily is required\"),\n fontSize: z.number().positive(\"fontSize must be positive\"),\n fontWeight: z.union([z.number(), z.enum([\"normal\", \"bold\"])]).optional(),\n fontStyle: z.enum([\"normal\", \"italic\"]).optional(),\n textAlign: z.enum([\"left\", \"center\", \"right\"]).optional(),\n lineHeight: z.number().positive().optional(),\n letterSpacing: z.number().optional(),\n color: ColorSchema,\n});\n","import { z } from \"zod\";\n\nexport const LinearEasingSchema = z.object({ type: z.literal(\"linear\") });\n\nexport const CubicBezierEasingSchema = z.object({\n type: z.literal(\"cubic-bezier\"),\n x1: z.number().min(0).max(1),\n y1: z.number(),\n x2: z.number().min(0).max(1),\n y2: z.number(),\n});\n\nexport const SpringEasingSchema = z.object({\n type: z.literal(\"spring\"),\n mass: z.number().positive().optional(),\n stiffness: z.number().positive().optional(),\n damping: z.number().positive().optional(),\n velocity: z.number().optional(),\n});\n\nexport const StepEasingSchema = z.object({\n type: z.literal(\"step\"),\n steps: z.number().int().positive(),\n position: z.enum([\"start\", \"end\"]).optional(),\n});\n\nexport const EasingPresetSchema = z.enum([\"linear\", \"ease-in\", \"ease-out\", \"ease-in-out\"]);\n\nexport const EasingSchema = z.union([\n LinearEasingSchema,\n CubicBezierEasingSchema,\n SpringEasingSchema,\n StepEasingSchema,\n EasingPresetSchema,\n]);\n","import { z } from \"zod\";\nimport { ColorSchema } from \"./color.js\";\n\nexport const ShadowSchema = z.object({\n color: ColorSchema,\n blur: z.number().min(0),\n offsetX: z.number().optional(),\n offsetY: z.number().optional(),\n});\n","import { z } from \"zod\";\nimport { ShapeSchema, FillSchema, StrokeSchema, TextStyleSchema, PathPointSchema } from \"./shape.js\";\nimport { FrameSchema, BoundsSchema, AnchorPointSchema } from \"./coordinates.js\";\nimport { ShadowSchema } from \"./shadow.js\";\nimport { InteractionSchema } from \"./interaction.js\";\n\nexport const BlendModeSchema = z.enum([\n \"normal\", \"multiply\", \"screen\", \"overlay\",\n \"darken\", \"lighten\", \"color-dodge\", \"color-burn\",\n \"hard-light\", \"soft-light\", \"difference\", \"exclusion\",\n \"hue\", \"saturation\", \"color\", \"luminosity\",\n]);\n\nexport const MotionPathSchema = z.object({\n points: z.array(PathPointSchema).min(2, \"Motion path must have at least 2 points\"),\n closed: z.boolean().optional(),\n autoRotate: z.boolean().optional(),\n autoRotateOffset: z.number().optional(),\n});\n\nexport const ShapeVisualSchema = z.object({\n type: z.literal(\"shape\"),\n shape: ShapeSchema,\n fill: FillSchema.optional(),\n stroke: StrokeSchema.optional(),\n});\n\nexport const TextVisualSchema = z.object({\n type: z.literal(\"text\"),\n content: z.string(),\n style: TextStyleSchema,\n});\n\nexport const SpritesheetConfigSchema = z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n});\n\nexport const SourceRectSchema = z.object({\n x: z.number(),\n y: z.number(),\n width: z.number().positive(),\n height: z.number().positive(),\n});\n\nexport const ImageVisualSchema = z.object({\n type: z.literal(\"image\"),\n assetId: z.string().min(1, \"assetId is required\"),\n src: z.string().optional(),\n sourceRect: SourceRectSchema.optional(),\n spritesheet: SpritesheetConfigSchema.optional(),\n frameIndex: z.number().int().min(0).optional(),\n});\n\nexport const VideoVisualSchema = z.object({\n type: z.literal(\"video\"),\n assetId: z.string().min(1, \"assetId is required\"),\n src: z.string().optional(),\n startFrame: z.number().int().min(0).optional(),\n sourceOffset: z.number().min(0).optional(),\n sourceEnd: z.number().positive().optional(),\n playbackRate: z.number().positive().optional(),\n volume: z.number().min(0).max(1).optional(),\n muted: z.boolean().optional(),\n objectFit: z.enum([\"contain\", \"cover\", \"fill\"]).optional(),\n});\n\nexport const AudioVisualSchema = z.object({\n type: z.literal(\"audio\"),\n assetId: z.string().min(1, \"assetId is required\"),\n src: z.string().optional(),\n startFrame: z.number().int().min(0).optional(),\n sourceOffset: z.number().min(0).optional(),\n sourceEnd: z.number().positive().optional(),\n playbackRate: z.number().positive().optional(),\n volume: z.number().min(0).max(1).optional(),\n muted: z.boolean().optional(),\n fadeIn: z.number().min(0).optional(),\n fadeOut: z.number().min(0).optional(),\n});\n\nexport const GroupVisualSchema = z.object({\n type: z.literal(\"group\"),\n});\n\nexport const RefVisualSchema = z.object({\n type: z.literal(\"ref\"),\n src: z.string().min(1, \"src is required\"),\n state: z.string().optional(),\n frame: z.number().int().min(0).optional(),\n});\n\nexport const VisualSchema = z.discriminatedUnion(\"type\", [\n ShapeVisualSchema,\n TextVisualSchema,\n ImageVisualSchema,\n VideoVisualSchema,\n AudioVisualSchema,\n GroupVisualSchema,\n RefVisualSchema,\n]);\n\nexport const LayerSchema = z.object({\n id: z.string().min(1, \"Layer id is required\"),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n visual: VisualSchema,\n frame: FrameSchema,\n bounds: BoundsSchema,\n anchorPoint: AnchorPointSchema.optional(),\n parentId: z.string().optional(),\n opacity: z.number().min(0).max(1).optional(),\n rotation: z.number().optional(),\n scale: z.object({ x: z.number(), y: z.number() }).optional(),\n visible: z.boolean().optional(),\n shadow: ShadowSchema.optional(),\n blendMode: BlendModeSchema.optional(),\n motionPath: MotionPathSchema.optional(),\n clipPath: ShapeSchema.optional(),\n tint: z.object({\n color: z.string(),\n amount: z.number().min(0).max(1),\n }).optional(),\n interactions: z.array(InteractionSchema).optional(),\n});\n","import { z } from \"zod\";\n\nexport const TriggerTypeSchema = z.enum([\n \"click\", \"hover\", \"pointerdown\", \"pointerup\", \"timer\", \"signal\",\n]);\n\nexport const TriggerSchema = z.object({\n type: TriggerTypeSchema,\n delay: z.number().nonnegative(\"Timer delay must be non-negative\").optional(),\n signal: z.string().optional(),\n}).refine(\n (t) => t.type !== \"timer\" || t.delay !== undefined,\n { message: \"Timer trigger requires a delay\" },\n).refine(\n (t) => t.type !== \"signal\" || t.signal !== undefined,\n { message: \"Signal trigger requires a signal name\" },\n);\n\nexport const ActionTypeSchema = z.enum([\n \"go-to-state\", \"emit-signal\", \"set-variable\", \"toggle-visibility\",\n]);\n\nexport const ActionSchema = z.object({\n type: ActionTypeSchema,\n state: z.string().optional(),\n signal: z.string().optional(),\n variable: z.string().optional(),\n value: z.unknown().optional(),\n targetLayer: z.string().optional(),\n}).refine(\n (a) => a.type !== \"go-to-state\" || a.state !== undefined,\n { message: \"go-to-state action requires a state name\" },\n).refine(\n (a) => a.type !== \"emit-signal\" || a.signal !== undefined,\n { message: \"emit-signal action requires a signal name\" },\n).refine(\n (a) => a.type !== \"set-variable\" || (a.variable !== undefined && a.value !== undefined),\n { message: \"set-variable action requires variable and value\" },\n);\n\nexport const InteractionSchema = z.object({\n id: z.string().min(1, \"Interaction id is required\"),\n trigger: TriggerSchema,\n action: ActionSchema,\n description: z.string().optional(),\n});\n","import { z } from \"zod\";\nimport { EasingSchema } from \"./easing.js\";\n\nexport const AnimatablePropertySchema = z.enum([\n \"frame.x\",\n \"frame.y\",\n \"bounds.width\",\n \"bounds.height\",\n \"opacity\",\n \"rotation\",\n \"scale.x\",\n \"scale.y\",\n \"anchorPoint.x\",\n \"anchorPoint.y\",\n \"visual.shape.cornerRadius\",\n \"visual.fill.color\",\n \"visual.stroke.color\",\n \"visual.stroke.width\",\n \"visual.stroke.start\",\n \"visual.stroke.end\",\n \"visual.style.fontSize\",\n \"visual.style.color\",\n \"shadow.color\",\n \"shadow.blur\",\n \"shadow.offsetX\",\n \"shadow.offsetY\",\n \"motionPath.progress\",\n \"visual.fill.angle\",\n \"visual.fill.center.x\",\n \"visual.fill.center.y\",\n \"visual.fill.radius\",\n \"visual.image.sourceRect.x\",\n \"visual.image.sourceRect.y\",\n \"visual.image.sourceRect.width\",\n \"visual.image.sourceRect.height\",\n \"visual.image.frameIndex\",\n \"visible\",\n \"tint.color\",\n \"tint.amount\",\n]);\n\nexport const FrameRangeSchema = z.tuple([\n z.number().int().min(0, \"Frame start must be >= 0\"),\n z.number().int().min(0, \"Frame end must be >= 0\"),\n]).refine(([start, end]) => end >= start, {\n message: \"Frame range end must be >= start\",\n});\n\nexport const DeltaSchema = z.object({\n id: z.string().optional(),\n name: z.string().optional(),\n layer: z.string().min(1, \"Delta must reference a layer id\"),\n property: AnimatablePropertySchema,\n range: FrameRangeSchema,\n from: z.unknown(),\n to: z.unknown(),\n easing: EasingSchema.optional(),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n});\n","import { z } from \"zod\";\nimport { DeltaSchema } from \"./delta.js\";\nimport { EasingSchema } from \"./easing.js\";\n\nexport const StateTransitionConfigSchema = z.object({\n duration: z.number().int().positive(\"Transition duration must be a positive integer (frames)\"),\n easing: EasingSchema.optional(),\n});\n\n/**\n * State schema — v1.0 removed `audio?: AudioSchema`. Audio is now a\n * first-class `AudioVisual` layer (see `layer.ts`); pre-1.0 documents that\n * still carry `state.audio` are tolerated by the legacy-friendly parser\n * (which drops the field via `passthrough` then strips on validate) but\n * authors should migrate.\n *\n * The strict StateSchema rejects unknown keys, so callers passing a\n * pre-1.0 doc through StateSchema.parse will fail on `audio`. Use\n * `parseAtelier` to migrate-on-read.\n */\nexport const StateSchema = z.object({\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n parent: z.string().optional(),\n duration: z.number().int().positive(\"State duration must be a positive integer (frames)\"),\n deltas: z.array(DeltaSchema),\n transitions: z.record(z.string(), StateTransitionConfigSchema).optional(),\n});\n","import { z } from \"zod\";\nimport { AnimatablePropertySchema } from \"./delta.js\";\nimport { EasingSchema } from \"./easing.js\";\n\nexport const PresetDeltaSchema = z.object({\n property: AnimatablePropertySchema,\n offset: z.tuple([z.number().int().min(0), z.number().int().min(0)]).optional(),\n from: z.unknown(),\n to: z.unknown(),\n easing: EasingSchema.optional(),\n});\n\nexport const PresetSchema = z.object({\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n deltas: z.array(PresetDeltaSchema).min(1, \"Preset must have at least one delta\"),\n});\n","import { z } from \"zod\";\n\nexport const VariableTypeSchema = z.enum([\"string\", \"number\", \"color\", \"asset\", \"boolean\"]);\n\nexport const VariableSchema = z.object({\n type: VariableTypeSchema,\n default: z.unknown().optional(),\n description: z.string().optional(),\n});\n","import { z } from \"zod\";\n\nexport const AssetTypeSchema = z.enum([\"image\", \"svg\", \"font\", \"animation\", \"audio\", \"video\"]);\n\nexport const AssetSchema = z.object({\n type: AssetTypeSchema,\n src: z.string().min(1, \"Asset src is required\"),\n description: z.string().optional(),\n spritesheet: z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n }).optional(),\n videoMeta: z.object({\n duration: z.number().positive(\"videoMeta.duration must be positive\"),\n fps: z.number().positive(\"videoMeta.fps must be positive\"),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n }).optional(),\n});\n","import { z } from \"zod\";\nimport { LayerSchema } from \"./layer.js\";\nimport { StateSchema } from \"./state.js\";\nimport { PresetSchema } from \"./preset.js\";\nimport { VariableSchema } from \"./variable.js\";\nimport { AssetSchema } from \"./asset.js\";\nimport { TimelineSchema } from \"./timeline.js\";\nimport { SlideRefSchema } from \"./slides.js\";\nimport { AtelierDesignSchema } from \"./design.js\";\n\nexport const CanvasSchema = z.object({\n width: z.number().int().positive(\"Canvas width must be a positive integer\"),\n height: z.number().int().positive(\"Canvas height must be a positive integer\"),\n fps: z.number().int().positive(\"FPS must be a positive integer\"),\n background: z.string().optional(),\n});\n\n/**\n * Project kind — controls which downstream exporters apply and which other\n * fields are meaningful. Absent = `\"video\"` for backcompat with pre-v1\n * documents. See `@a-company/atelier-types/document.ts` for the full\n * narrative.\n */\nexport const ProjectKindSchema = z.enum([\"video\", \"image\", \"carousel\"]);\n\nexport const AtelierDocumentSchema = z.object({\n version: z.string().min(1, \"Version is required\"),\n name: z.string().min(1, \"Animation name is required\"),\n kind: ProjectKindSchema.optional(),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n canvas: CanvasSchema,\n /** Per-file design / brand block (self-contained — no auto-merge). */\n design: AtelierDesignSchema.optional(),\n variables: z.record(z.string(), VariableSchema).optional(),\n assets: z.record(z.string(), AssetSchema).optional(),\n presets: z.record(z.string(), PresetSchema).optional(),\n layers: z.array(LayerSchema),\n states: z.record(z.string(), StateSchema),\n /** Derived timeline summary for video-kind projects. Optional. */\n timeline: TimelineSchema.optional(),\n /** Carousel slides — only meaningful when kind === \"carousel\". */\n slides: z.array(SlideRefSchema).optional(),\n});\n","import { z } from \"zod\";\n\n/**\n * Timeline summary schemas — see `@a-company/atelier-types/timeline.ts` for\n * semantics (derived overview of clip placements, regenerated by writers,\n * tolerated as missing/stale by readers).\n */\n\nexport const TimelineClipSchema = z.object({\n layerId: z.string().min(1, \"TimelineClip.layerId is required\"),\n startFrame: z.number().int().min(0, \"startFrame must be a non-negative integer\"),\n endFrame: z.number().int().min(0, \"endFrame must be a non-negative integer\"),\n source: z.string().min(1, \"TimelineClip.source is required\"),\n});\n\nexport const TimelineTrackSchema = z.object({\n id: z.string().min(1, \"TimelineTrack.id is required\"),\n kind: z.enum([\"video\", \"audio\"]),\n clips: z.array(TimelineClipSchema),\n});\n\nexport const TimelineSchema = z.object({\n fps: z.number().int().positive(\"Timeline.fps must be a positive integer\"),\n totalFrames: z.number().int().min(0, \"Timeline.totalFrames must be a non-negative integer\"),\n tracks: z.array(TimelineTrackSchema),\n});\n","import { z } from \"zod\";\n\n/**\n * Carousel slide schemas — see `@a-company/atelier-types/slides.ts` for\n * semantics. SlideRef.src points at any `.atelier` file in the workspace;\n * cycle detection is the resolver's responsibility (not enforced here).\n */\n\nexport const SlideTransitionSchema = z.object({\n kind: z.enum([\"cut\", \"crossfade\", \"fade\"]),\n durationFrames: z.number().int().min(0, \"transition durationFrames must be a non-negative integer\").optional(),\n color: z.string().optional(),\n});\n\nexport const SlideRefSchema = z.object({\n src: z.string().min(1, \"SlideRef.src is required\"),\n duration: z.number().int().min(0, \"SlideRef.duration must be a non-negative integer (frames)\").optional(),\n transition: SlideTransitionSchema.optional(),\n label: z.string().optional(),\n});\n","import { z } from \"zod\";\n\n/**\n * Per-file design block schemas — see `@a-company/atelier-types/design.ts`\n * for semantics. Self-contained per file; lineage is explicit via\n * `relatedTo[]` (no auto-merge at render time).\n */\n\nexport const DesignRelationSchema = z.enum([\"derived-from\", \"sibling\", \"references\"]);\n\nexport const AtelierDesignRelationSchema = z.object({\n source: z.string().min(1, \"AtelierDesignRelation.source is required\"),\n relation: DesignRelationSchema,\n note: z.string().optional(),\n});\n\nexport const DesignTypographySchema = z.object({\n headingFamily: z.string().optional(),\n bodyFamily: z.string().optional(),\n monoFamily: z.string().optional(),\n sizes: z.record(z.string(), z.number().positive()).optional(),\n weights: z.record(z.string(), z.string()).optional(),\n});\n\nexport const DesignMotionSchema = z.object({\n defaultEasing: z.string().optional(),\n defaultDuration: z.number().int().positive().optional(),\n});\n\nexport const AtelierDesignSchema = z.object({\n palette: z.record(z.string(), z.string()).optional(),\n typography: DesignTypographySchema.optional(),\n motion: DesignMotionSchema.optional(),\n relatedTo: z.array(AtelierDesignRelationSchema).optional(),\n});\n","import { z } from \"zod\";\n\n/** Silence-trim policy block */\nexport const SilencePolicySchema = z.object({\n noise: z.string().optional(),\n min_silence: z.number().nonnegative().optional(),\n default_padding_pre: z.number().nonnegative().optional(),\n default_padding_post: z.number().nonnegative().optional(),\n match_tolerance: z.number().nonnegative().optional(),\n}).strict();\n\n/** Caption visual style block */\nexport const CaptionStyleSchema = z.object({\n font_family: z.string().optional(),\n font_size: z.number().positive().optional(),\n font_weight: z.union([z.literal(\"normal\"), z.literal(\"bold\"), z.number()]).optional(),\n text_align: z.enum([\"left\", \"center\", \"right\"]).optional(),\n color: z.string().optional(),\n y_ratio: z.number().min(0).max(1).optional(),\n width_ratio: z.number().min(0).max(1).optional(),\n fade_seconds: z.number().nonnegative().optional(),\n}).strict();\n\n/** Caption phrase grouping block */\nexport const CaptionGroupingSchema = z.object({\n max_words: z.number().int().positive().optional(),\n pause_gap: z.number().nonnegative().optional(),\n}).strict();\n\n/** Anchor enum shared by every overlay sub-rule */\nexport const OverlayAnchorSchema = z.enum([\n \"top-left\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-right\",\n]);\n\n/** Visual subset for overlay text — recipe snake_case convention */\nexport const OverlayTextStyleSchema = z.object({\n font_family: z.string().optional(),\n font_size: z.number().positive().optional(),\n font_weight: z.union([z.literal(\"normal\"), z.literal(\"bold\"), z.number()]).optional(),\n color: z.string().optional(),\n}).strict();\n\n/**\n * Validate a page-number format template:\n * - braces must balance\n * - every {…} group must match (current|total)(:0Nd)? (zero-pad form)\n * - at least one of {current} / {total} must appear\n *\n * Render-time substitution is a separate concern; this only validates syntax.\n */\nfunction validatePageNumberFormat(\n format: string,\n ctx: z.RefinementCtx,\n): void {\n if (format.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"format must be a non-empty string\",\n });\n return;\n }\n\n const open = (format.match(/\\{/g) ?? []).length;\n const close = (format.match(/\\}/g) ?? []).length;\n if (open !== close) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `format has unbalanced braces (${open} '{' vs ${close} '}')`,\n });\n return;\n }\n\n const groupRe = /\\{([^{}]*)\\}/g;\n const groupRule = /^(current|total)(:0\\d+d)?$/;\n let m: RegExpExecArray | null;\n let sawCurrent = false;\n let sawTotal = false;\n while ((m = groupRe.exec(format)) !== null) {\n const inner = m[1];\n if (!groupRule.test(inner)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `format placeholder \"{${inner}}\" is not recognized — expected {current}, {total}, {current:0Nd}, or {total:0Nd}`,\n });\n return;\n }\n if (inner.startsWith(\"current\")) sawCurrent = true;\n if (inner.startsWith(\"total\")) sawTotal = true;\n }\n\n if (!sawCurrent && !sawTotal) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"format must contain at least one {current} or {total} placeholder\",\n });\n }\n}\n\n/** Handle overlay rule schema — anchored creator-handle text */\nexport const OverlayHandleRuleSchema = z.object({\n text: z.string().min(1),\n anchor: OverlayAnchorSchema,\n margin: z.number().nonnegative().optional(),\n style: OverlayTextStyleSchema.optional(),\n}).strict();\n\n/** Page-number overlay rule schema — anchored \"1/5\"-style indicator */\nexport const OverlayPageNumberRuleSchema = z.object({\n format: z.string().superRefine(validatePageNumberFormat),\n anchor: OverlayAnchorSchema,\n margin: z.number().nonnegative().optional(),\n style: OverlayTextStyleSchema.optional(),\n}).strict();\n\n/** Overlay rules block (Phase 1.5) — both sub-blocks optional */\nexport const OverlayRulesSchema = z.object({\n handle: OverlayHandleRuleSchema.optional(),\n page_number: OverlayPageNumberRuleSchema.optional(),\n}).strict();\n\n/**\n * StudioRecipe — top-level. Reserved fields (caption_highlight, transition_kit,\n * etc.) still accept any shape; Phase 3 will refine them. Validate-time warnings\n * surface reserved-fields-in-use to authors so they aren't caught off-guard\n * when those sections become load-bearing.\n *\n * overlay_rules was promoted from reserved Phase 3 to first-class Phase 1.5.\n */\nexport const StudioRecipeSchema = z.object({\n version: z.string(),\n name: z.string(),\n description: z.string().optional(),\n author: z.string().optional(),\n tags: z.array(z.string()).optional(),\n\n silence_policy: SilencePolicySchema.optional(),\n caption_style: CaptionStyleSchema.optional(),\n caption_grouping: CaptionGroupingSchema.optional(),\n\n // Phase 1.5 — first-class overlay rules\n overlay_rules: OverlayRulesSchema.optional(),\n\n // Reserved — Phase 3 (parse-opaque)\n caption_highlight: z.unknown().optional(),\n transition_kit: z.unknown().optional(),\n palette: z.unknown().optional(),\n audio_policy: z.unknown().optional(),\n aspect_targets: z.array(z.unknown()).optional(),\n}).strict();\n\n/** Names of still-reserved fields — used by validators to emit forward-compat warnings */\nexport const RESERVED_RECIPE_FIELDS = [\n \"caption_highlight\",\n \"transition_kit\",\n \"palette\",\n \"audio_policy\",\n \"aspect_targets\",\n] as const;\n","import type { AtelierDocument, Layer, Delta, VideoVisual, StudioRecipe } from \"@a-company/atelier-types\";\nimport { AtelierDocumentSchema } from \"./document.js\";\nimport { LayerSchema } from \"./layer.js\";\nimport { DeltaSchema } from \"./delta.js\";\nimport { StudioRecipeSchema, RESERVED_RECIPE_FIELDS } from \"./recipe.js\";\nimport type { z } from \"zod\";\n\n/** Validation result — either success with typed data or failure with readable errors */\nexport type ValidationResult<T> =\n | { success: true; data: T }\n | { success: false; errors: ValidationError[] };\n\nexport interface ValidationError {\n path: string;\n message: string;\n}\n\n/** Format Zod errors into flat, AI-readable error messages */\nfunction formatErrors(error: z.ZodError): ValidationError[] {\n return error.issues.map((issue) => ({\n path: issue.path.join(\".\") || \"(root)\",\n message: issue.message,\n }));\n}\n\n/** Validate a complete AtelierDocument */\nexport function validateDocument(input: unknown): ValidationResult<AtelierDocument> {\n const result = AtelierDocumentSchema.safeParse(input);\n if (result.success) {\n return { success: true, data: result.data as AtelierDocument };\n }\n return { success: false, errors: formatErrors(result.error) };\n}\n\n/** Validate a single Layer */\nexport function validateLayer(input: unknown): ValidationResult<Layer> {\n const result = LayerSchema.safeParse(input);\n if (result.success) {\n return { success: true, data: result.data as Layer };\n }\n return { success: false, errors: formatErrors(result.error) };\n}\n\n/** Validate a single Delta */\nexport function validateDelta(input: unknown): ValidationResult<Delta> {\n const result = DeltaSchema.safeParse(input);\n if (result.success) {\n return { success: true, data: result.data as Delta };\n }\n return { success: false, errors: formatErrors(result.error) };\n}\n\n/**\n * Validate a VideoVisual layer against semantic constraints (^valid-video-layer gate).\n * Checks beyond Zod: sourceEnd > sourceOffset, sourceEnd ≤ videoMeta.duration.\n */\nexport function validateVideoLayer(\n visual: VideoVisual,\n videoMetaDuration?: number,\n): ValidationResult<VideoVisual> {\n const errors: ValidationError[] = [];\n\n if (!visual.assetId) {\n errors.push({ path: \"assetId\", message: \"assetId is required\" });\n }\n\n const sourceOffset = visual.sourceOffset ?? 0;\n if (visual.sourceEnd !== undefined) {\n if (visual.sourceEnd <= sourceOffset) {\n errors.push({\n path: \"sourceEnd\",\n message: `sourceEnd (${visual.sourceEnd}) must be greater than sourceOffset (${sourceOffset})`,\n });\n }\n if (videoMetaDuration !== undefined && visual.sourceEnd > videoMetaDuration) {\n errors.push({\n path: \"sourceEnd\",\n message: `sourceEnd (${visual.sourceEnd}) exceeds asset duration (${videoMetaDuration})`,\n });\n }\n }\n\n if (videoMetaDuration !== undefined && sourceOffset >= videoMetaDuration) {\n errors.push({\n path: \"sourceOffset\",\n message: `sourceOffset (${sourceOffset}) is at or beyond asset duration (${videoMetaDuration})`,\n });\n }\n\n if (errors.length > 0) return { success: false, errors };\n return { success: true, data: visual };\n}\n\n/**\n * Validate a StudioRecipe against the schema (^valid-recipe gate).\n * Returns success with the parsed recipe and optional warnings about\n * reserved-but-unimplemented Phase 3 fields that are present.\n */\nexport function validateRecipe(\n recipe: unknown,\n): ValidationResult<StudioRecipe> & { warnings?: string[] } {\n const parsed = StudioRecipeSchema.safeParse(recipe);\n if (!parsed.success) {\n return { success: false, errors: formatErrors(parsed.error) };\n }\n\n const warnings: string[] = [];\n const data = parsed.data as StudioRecipe;\n for (const field of RESERVED_RECIPE_FIELDS) {\n if (data[field] !== undefined) {\n warnings.push(\n `${field} is reserved for Phase 3 and currently has no effect.`,\n );\n }\n }\n\n return { success: true, data, ...(warnings.length > 0 && { warnings }) };\n}\n","import { parse as yamlParse, stringify as yamlStringify } from \"yaml\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { validateDocument } from \"./validate.js\";\nimport type { ValidationResult } from \"./validate.js\";\n\n/**\n * Parse a YAML string into a validated AtelierDocument.\n * Returns validation errors if the YAML is invalid or doesn't match the schema.\n */\nexport function parseAtelier(yamlString: string): ValidationResult<AtelierDocument> {\n let parsed: unknown;\n try {\n parsed = yamlParse(yamlString);\n } catch (err) {\n return {\n success: false,\n errors: [{ path: \"(yaml)\", message: `YAML parse error: ${(err as Error).message}` }],\n };\n }\n return validateDocument(parsed);\n}\n\n/**\n * Serialize an AtelierDocument to YAML string.\n */\nexport function serializeAtelier(doc: AtelierDocument): string {\n return yamlStringify(doc, { indent: 2 });\n}\n","import { z } from \"zod\";\n\n/**\n * Slot reference vocabulary (front-of-pipeline artifacts spec §5).\n *\n * Format: `<kind>.<open-tail>` where `<open-tail>` is one or more\n * dot-separated segments. The canonical form per spec §5 is\n * `<kind>.<category>.<specifier>` (three segments), but the spec's own\n * STORYBOARD example mixes longer (`audio.sfx.transition.whoosh`, four\n * segments) and shorter (`font.display`, two segments) forms. We reconcile\n * by enforcing the contract that's stable across both: `kind` is closed,\n * everything after the first dot is open.\n *\n * - `kind` is a CLOSED enum (the seven asset-family roots).\n * - At least one open segment must follow the kind.\n *\n * Aligns conceptually with `VariableSchema`'s `asset` type — both are the\n * inert-reference surface that the mind-map binds at compose time (TD-229).\n */\nexport const SlotKindSchema = z.enum([\n \"image\",\n \"video\",\n \"audio\",\n \"text\",\n \"font\",\n \"voice\",\n \"logo\",\n]);\n\nexport type SlotKind = z.infer<typeof SlotKindSchema>;\n\nexport const SLOT_KINDS = SlotKindSchema.options;\n\n/**\n * Parse a slot reference into its segments. Returns null if the string\n * does not satisfy `<kind>.<tail>` (where `<tail>` has at least one\n * segment); otherwise returns the kind plus the logical category and\n * specifier. When only two segments are present (e.g. `font.display`),\n * `category` carries the open segment and `specifier` is the empty string.\n */\nexport function parseSlotRef(ref: string): { kind: SlotKind; category: string; specifier: string } | null {\n if (typeof ref !== \"string\" || ref.length === 0) return null;\n const segments = ref.split(\".\");\n if (segments.length < 2) return null;\n if (segments.some((s) => s.length === 0)) return null;\n const [rawKind, category, ...rest] = segments;\n const kindParsed = SlotKindSchema.safeParse(rawKind);\n if (!kindParsed.success) return null;\n const specifier = rest.join(\".\");\n return { kind: kindParsed.data, category, specifier };\n}\n\n/**\n * Zod schema for a single slot reference string. Refuses unknown `kind`\n * segments; permits any open `category.specifier`. The specifier may\n * itself contain dots (e.g. `audio.sfx.transition.whoosh`).\n */\nexport const SlotRefSchema = z.string().superRefine((value, ctx) => {\n const parsed = parseSlotRef(value);\n if (parsed !== null) return;\n // Distinguish \"unknown kind\" from \"shape wrong\" for clearer errors.\n const segments = value.split(\".\");\n if (segments.length < 2) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `slot reference \"${value}\" must have at least two segments (<kind>.<open-tail>)`,\n });\n return;\n }\n if (segments.some((s) => s.length === 0)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `slot reference \"${value}\" has an empty segment`,\n });\n return;\n }\n const kindOk = SlotKindSchema.safeParse(segments[0]).success;\n if (!kindOk) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `slot reference \"${value}\" has unknown kind \"${segments[0]}\" — expected one of ${SLOT_KINDS.join(\", \")}`,\n });\n return;\n }\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `slot reference \"${value}\" is malformed`,\n });\n});\n","import { z } from \"zod\";\n\n/**\n * Animation Technique Library (front-of-pipeline artifacts spec §5).\n *\n * STORYBOARD beats declare `technique_library_version` and pull techniques\n * by string name from the library at that version. Iris refuses unknown\n * techniques at compose time. The schema itself only validates that\n * `techniques: string[]` — membership against the active library is\n * enforced by `validateArtifactSet` so the pure-Zod schema stays version-\n * agnostic.\n *\n * Versioning policy: integer (per artifact spec §9 Q4). Bump on additive\n * changes; older STORYBOARDs continue to declare their original version.\n * Library versions are SUPERSETS: v(n+1) contains every entry from v(n) so\n * a creator's existing storyboard never breaks when the library moves\n * forward.\n */\nexport const TechniqueLibrarySchema = z.object({\n version: z.number().int().positive(),\n techniques: z.array(z.string().min(1)),\n}).strict();\n\nexport type TechniqueLibrary = z.infer<typeof TechniqueLibrarySchema>;\n\n/**\n * Version 1 starter set — drawn from the artifact spec's STORYBOARD EXAMPLE.\n * Additions land in higher versions; v1 stays frozen.\n */\nexport const TECHNIQUE_LIBRARY_V1: TechniqueLibrary = {\n version: 1,\n techniques: [\n \"text.split-reveal\",\n \"image.ken-burns.slow\",\n \"super.weight-pulse-on-keyword\",\n \"background.color-shift-to-token\",\n ],\n};\n\n/**\n * Version 2 — additive expansion for Iris's animation craft. Twelve new\n * techniques cover text, image, transition, super (overlay text), and audio\n * categories so STORYBOARD can call for them by name and Iris's\n * compose-from-primitives skill knows how to lower each one to MCP calls.\n *\n * Every v1 entry is preserved (supersets, not replacements).\n */\nexport const TECHNIQUE_LIBRARY_V2: TechniqueLibrary = {\n version: 2,\n techniques: [\n // v1 (preserved)\n \"text.split-reveal\",\n \"image.ken-burns.slow\",\n \"super.weight-pulse-on-keyword\",\n \"background.color-shift-to-token\",\n // v2 additions — text\n \"text.kinetic-keyword-emphasis\",\n \"text.typewriter\",\n // v2 additions — image\n \"image.zoom-in-during-beat\",\n \"image.cross-dissolve\",\n \"image.parallax-pan-slow\",\n // v2 additions — transition\n \"transition.whip-pan\",\n \"transition.match-cut\",\n \"transition.morph-cut\",\n \"transition.fade-through-color\",\n // v2 additions — super (overlay text)\n \"super.scale-in-spring\",\n \"super.drop-in-staggered\",\n // v2 additions — audio\n \"audio.fade-under-vo\",\n ],\n};\n\n/** Registry of all shipped technique-library versions. Keyed by integer version. */\nexport const TECHNIQUE_LIBRARIES: Record<number, TechniqueLibrary> = {\n 1: TECHNIQUE_LIBRARY_V1,\n 2: TECHNIQUE_LIBRARY_V2,\n};\n\n/** The current/latest shipped library version. */\nexport const CURRENT_TECHNIQUE_LIBRARY_VERSION = 2;\n\n/** Resolve a library by version; returns null if the version is not shipped. */\nexport function getTechniqueLibrary(version: number): TechniqueLibrary | null {\n return TECHNIQUE_LIBRARIES[version] ?? null;\n}\n","import { z } from \"zod\";\n\n/**\n * DESIGN.md — the creative-direction artifact (front-of-pipeline spec §3).\n *\n * Authored by Quill. Captures the brand register the entire Project must\n * respect: audience, voice, visual register, constraints, brand references.\n * When a recipe is attached, DESIGN defers to the recipe and only records\n * `variances` — divergences from the recipe.\n *\n * Every sub-schema is `.strict()` to match the recipe-package convention\n * (unknown keys are a hard error, not silently dropped — see the package-\n * level `recipe-strict-no-unknown-keys` aspect).\n */\n\n/** audience block — primary/secondary/platform list */\nexport const DesignAudienceSchema = z.object({\n primary: z.string().min(1),\n secondary: z.string().optional(),\n platform: z.array(z.string().min(1)).min(1),\n}).strict();\n\n/** voice block — descriptors are an ordered 3-to-5 list */\nexport const DesignVoiceSchema = z.object({\n descriptors: z.array(z.string().min(1)).min(3).max(5),\n references: z.array(z.string().min(1)).optional(),\n}).strict();\n\n/** Palette roles — closed enum per spec §3 (\"Roles are an enum, not free text\") */\nexport const PaletteRoleSchema = z.enum([\n \"background\",\n \"surface\",\n \"primary\",\n \"accent\",\n \"text-on-dark\",\n \"text-on-light\",\n]);\n\n/** Single palette entry — token + hex + role */\nexport const PaletteEntrySchema = z.object({\n token: z.string().min(1),\n hex: z.string().regex(/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, {\n message: \"hex must be a #RGB / #RRGGBB / #RRGGBBAA string\",\n }),\n role: PaletteRoleSchema,\n}).strict();\n\n/** Typography usage enum — closed */\nexport const TypographyUsageSchema = z.enum([\"display\", \"body\", \"caption\", \"mono\"]);\n\n/** Typography entry */\nexport const TypographyEntrySchema = z.object({\n token: z.string().min(1),\n family: z.string().min(1),\n weights: z.array(z.number().int().min(1).max(1000)).min(1),\n usage: TypographyUsageSchema,\n}).strict();\n\n/** motion_register sub-block — tempo / easing_bias / camera_bias */\nexport const MotionRegisterSchema = z.object({\n tempo: z.enum([\"snappy\", \"steady\", \"calm\", \"languid\"]),\n easing_bias: z.enum([\"linear\", \"ease-out\", \"spring\"]),\n camera_bias: z.enum([\"static\", \"drift\", \"snap\"]).optional(),\n}).strict();\n\n/** visual_register block — palette + typography + motion_register */\nexport const VisualRegisterSchema = z.object({\n palette: z.array(PaletteEntrySchema).min(1),\n typography: z.array(TypographyEntrySchema).min(1),\n motion_register: MotionRegisterSchema,\n}).strict();\n\n/** Aspect ratios — closed enum per spec §3 */\nexport const AspectRatioSchema = z.enum([\"9:16\", \"1:1\", \"16:9\", \"4:5\"]);\n\n/** constraints block — duration, aspect ratios, do_not list */\nexport const DesignConstraintsSchema = z.object({\n max_duration_seconds: z.number().positive().optional(),\n aspect_ratios: z.array(AspectRatioSchema).min(1),\n do_not: z.array(z.string().min(1)),\n}).strict();\n\n/** Logo brand reference — closed role enum */\nexport const BrandLogoSchema = z.object({\n token: z.string().min(1),\n role: z.enum([\"primary\", \"mark\", \"wordmark\"]),\n}).strict();\n\n/** Handle brand reference — platform + value */\nexport const BrandHandleSchema = z.object({\n platform: z.string().min(1),\n value: z.string().min(1),\n}).strict();\n\n/** brand_references block — logos + handles + page-number convention */\nexport const BrandReferencesSchema = z.object({\n logos: z.array(BrandLogoSchema).min(1),\n handles: z.array(BrandHandleSchema).optional(),\n page_number_convention: z.string().optional(),\n}).strict();\n\n/**\n * Variance entry — structured form per spec §9 Q5 recommendation:\n * { field, value, reason }. Agents diff variances; free-text Markdown\n * would be opaque to them.\n */\nexport const DesignVarianceSchema = z.object({\n field: z.string().min(1),\n value: z.unknown(),\n reason: z.string().min(1),\n}).strict();\n\n/**\n * DesignArtifactSchema — the typed frontmatter shape. The Markdown body\n * is carried as a `body: string` field set by the parser (verbatim — voice\n * notes, prose, etc. live there).\n */\nexport const DesignArtifactSchema = z.object({\n audience: DesignAudienceSchema,\n voice: DesignVoiceSchema,\n visual_register: VisualRegisterSchema,\n constraints: DesignConstraintsSchema,\n brand_references: BrandReferencesSchema,\n variances: z.array(DesignVarianceSchema).optional(),\n /** Markdown body verbatim — attached by the parser, not part of frontmatter. */\n body: z.string(),\n}).strict();\n\nexport type DesignArtifact = z.infer<typeof DesignArtifactSchema>;\n","import { z } from \"zod\";\nimport { SlotRefSchema } from \"./slot.js\";\n\n/**\n * SCRIPT.md — the narrative artifact (front-of-pipeline spec §4).\n *\n * Authored by Quill, refined by Lux. Two modes — discriminated union on\n * `mode`:\n * - `narrated`: four ordered blocks (hook/story/proof/cta), each a list\n * of beats with optional `bind_to_transcript` for post-VO rebinding.\n * - `carousel` | `text-only`: flat ordered list of beats; no transcript\n * binding (no VO exists).\n *\n * Every sub-schema is `.strict()` per the package convention.\n */\n\n/** Kebab-case beat-id pattern — also accepts `b-roll.<rest>` prefix used by STORYBOARD. */\nconst BEAT_ID_RE = /^[a-z][a-z0-9-]*(\\.[a-z0-9][a-z0-9-]*)*$/;\n\n/** Beat-id schema — kebab-case, may contain dot-prefixed namespaces like `b-roll.intro`. */\nexport const ScriptBeatIdSchema = z.string().regex(BEAT_ID_RE, {\n message: \"beat id must be kebab-case (optionally dot-namespaced, e.g. `proof-1` or `b-roll.intro`)\",\n});\n\n/** Narrated-mode beat — has `bind_to_transcript` (default true). */\nexport const NarratedBeatSchema = z.object({\n id: ScriptBeatIdSchema,\n copy: z.string().min(1),\n intent: z.string().min(1),\n est_duration_s: z.number().nonnegative(),\n bind_to_transcript: z.boolean().default(true),\n}).strict();\n\nexport type NarratedBeat = z.infer<typeof NarratedBeatSchema>;\n\n/** Non-narrated beat — carousel / text-only; no transcript binding field. */\nexport const NonNarratedBeatSchema = z.object({\n id: ScriptBeatIdSchema,\n copy: z.string().min(1),\n intent: z.string().min(1),\n est_duration_s: z.number().nonnegative(),\n}).strict();\n\nexport type NonNarratedBeat = z.infer<typeof NonNarratedBeatSchema>;\n\n/** Narrated-mode body: four ordered blocks. */\nexport const NarratedBlocksSchema = z.object({\n hook: z.array(NarratedBeatSchema).min(1),\n story: z.array(NarratedBeatSchema),\n proof: z.array(NarratedBeatSchema),\n cta: z.array(NarratedBeatSchema).min(1),\n}).strict();\n\n/**\n * The script mode is a discriminated union on `mode`. Top-level fields:\n * mode, target_duration_s, language, tts_voice?\n * Plus the beat structure: narrated has four blocks; carousel/text-only\n * has a flat `beats` list.\n */\nexport const NarratedScriptSchema = z.object({\n mode: z.literal(\"narrated\"),\n target_duration_s: z.number().positive(),\n language: z.string().min(1),\n /** Optional slot reference for TTS voice (e.g. `voice.host.primary`). */\n tts_voice: SlotRefSchema.optional(),\n blocks: NarratedBlocksSchema,\n /** Markdown body verbatim — attached by the parser when the body has stray prose. */\n body: z.string(),\n}).strict();\n\nexport const CarouselScriptSchema = z.object({\n mode: z.literal(\"carousel\"),\n target_duration_s: z.number().positive(),\n language: z.string().min(1),\n tts_voice: SlotRefSchema.optional(),\n beats: z.array(NonNarratedBeatSchema).min(1),\n body: z.string(),\n}).strict();\n\nexport const TextOnlyScriptSchema = z.object({\n mode: z.literal(\"text-only\"),\n target_duration_s: z.number().positive(),\n language: z.string().min(1),\n tts_voice: SlotRefSchema.optional(),\n beats: z.array(NonNarratedBeatSchema).min(1),\n body: z.string(),\n}).strict();\n\n/** ScriptArtifactSchema — discriminated union across the three modes. */\nexport const ScriptArtifactSchema = z.discriminatedUnion(\"mode\", [\n NarratedScriptSchema,\n CarouselScriptSchema,\n TextOnlyScriptSchema,\n]);\n\nexport type ScriptArtifact = z.infer<typeof ScriptArtifactSchema>;\nexport type NarratedScript = z.infer<typeof NarratedScriptSchema>;\nexport type CarouselScript = z.infer<typeof CarouselScriptSchema>;\nexport type TextOnlyScript = z.infer<typeof TextOnlyScriptSchema>;\n\n/**\n * Flatten all beats from a script regardless of mode — useful for\n * cross-artifact validation and duration summing.\n */\nexport function allScriptBeats(script: ScriptArtifact): Array<NarratedBeat | NonNarratedBeat> {\n if (script.mode === \"narrated\") {\n return [\n ...script.blocks.hook,\n ...script.blocks.story,\n ...script.blocks.proof,\n ...script.blocks.cta,\n ];\n }\n return script.beats;\n}\n","import { z } from \"zod\";\nimport { SlotRefSchema } from \"./slot.js\";\nimport { ScriptBeatIdSchema } from \"./script.js\";\n\n/**\n * STORYBOARD.md — the composition artifact (front-of-pipeline spec §5).\n *\n * Authored by Lux. One storyboard beat per script beat (matching `id`),\n * plus optional storyboard-only beats prefixed `b-roll.*`.\n *\n * Iris walks this file beat by beat to mutate the live AtelierDocument.\n * Techniques are validated string-level here; library-version membership\n * is enforced by `validateArtifactSet` so the schema stays version-agnostic.\n *\n * Every sub-schema is `.strict()` per the package convention.\n */\n\n/** Beat time window — `start_s` < `end_s` enforced by refine. */\nexport const BeatWindowSchema = z.object({\n start_s: z.number().nonnegative(),\n end_s: z.number().nonnegative(),\n}).strict().refine((w) => w.end_s > w.start_s, {\n message: \"window.end_s must be > window.start_s\",\n});\n\n/** Camera block — closed kind enum, optional subject string. */\nexport const CameraSchema = z.object({\n kind: z.enum([\"static\", \"drift\", \"push\", \"pull\", \"whip\"]),\n subject: z.string().min(1).optional(),\n}).strict();\n\n/**\n * Mood adjectives — closed-ish vocabulary per spec §5. The spec lists\n * `tense | warm | clinical | mischievous | ...` with an explicit \"...\",\n * signalling the canonical set is open to extension. We validate\n * non-empty kebab-ish strings rather than enforce membership; the closed\n * set lives at the agent layer where it has UX consequence.\n */\nexport const MoodSchema = z.string().min(1);\n\n/** Transition-out kind — closed enum per spec §5. */\nexport const TransitionKindSchema = z.enum([\"cut\", \"dip-to-color\", \"whip\", \"crossfade\"]);\n\n/**\n * transition_out — the move out of this beat. `color` is a DESIGN\n * palette-token reference (e.g. `ember`), NOT a slot reference, so it is\n * a plain string here. Validation of token-existence is a cross-artifact\n * concern handled outside this schema.\n */\nexport const TransitionOutSchema = z.object({\n kind: TransitionKindSchema,\n duration_s: z.number().nonnegative().optional(),\n color: z.string().min(1).optional(),\n}).strict();\n\n/** A single SFX entry on a beat — a slot ref + gain. */\nexport const SfxEntrySchema = z.object({\n slot: SlotRefSchema,\n gain_db: z.number(),\n}).strict();\n\n/** Single storyboard beat. */\nexport const StoryboardBeatSchema = z.object({\n id: ScriptBeatIdSchema,\n window: BeatWindowSchema,\n mood: z.array(MoodSchema).min(1),\n camera: CameraSchema,\n slots: z.array(SlotRefSchema),\n techniques: z.array(z.string().min(1)),\n transition_out: TransitionOutSchema,\n sfx: z.array(SfxEntrySchema).optional(),\n}).strict();\n\nexport type StoryboardBeat = z.infer<typeof StoryboardBeatSchema>;\n\n/** Aspect ratios — closed enum (matches DESIGN's). Inlined to avoid a circular import. */\nexport const StoryboardAspectRatioSchema = z.enum([\"9:16\", \"1:1\", \"16:9\", \"4:5\"]);\n\n/** StoryboardArtifactSchema — frontmatter + ordered beats. */\nexport const StoryboardArtifactSchema = z.object({\n technique_library_version: z.number().int().positive(),\n aspect_ratio: StoryboardAspectRatioSchema,\n beats: z.array(StoryboardBeatSchema).min(1),\n}).strict();\n\nexport type StoryboardArtifact = z.infer<typeof StoryboardArtifactSchema>;\n\n/** True if a storyboard beat id is in the b-roll namespace (script-id exempt). */\nexport function isBRollBeatId(id: string): boolean {\n return id.startsWith(\"b-roll.\");\n}\n","import { parse as yamlParse, stringify as yamlStringify } from \"yaml\";\nimport { DesignArtifactSchema } from \"./design.js\";\nimport type { DesignArtifact } from \"./design.js\";\nimport {\n ScriptArtifactSchema,\n NarratedScriptSchema,\n NarratedBeatSchema,\n NonNarratedBeatSchema,\n type ScriptArtifact,\n} from \"./script.js\";\nimport { StoryboardArtifactSchema, type StoryboardArtifact } from \"./storyboard.js\";\n\n/**\n * Parsers for the three front-of-pipeline artifacts (DESIGN.md, SCRIPT.md,\n * STORYBOARD.md). Universal file shape:\n *\n * ---\n * <YAML frontmatter>\n * ---\n * <Markdown body>\n *\n * For DESIGN, the body is free prose (kept verbatim as `body`).\n * For SCRIPT, the body has `# Hook | # Story | # Proof | # CTA` headings\n * with YAML-list beats — or, in carousel/text-only modes, a flat\n * beat list. The parser lifts beats out of the body into typed fields.\n * For STORYBOARD, the body has `## <beat-id>` headings followed by a\n * YAML mapping block; the parser lifts beats into typed fields.\n *\n * Each parser returns a fully-validated artifact (throws z.ZodError on\n * structural failure — callers wrap as needed). Serializers emit a\n * canonical form so round-trip-then-re-parse is structurally stable.\n */\n\nconst FRONTMATTER_FENCE = \"---\";\n\n/** Internal: split a raw artifact string into its YAML frontmatter and body. */\nexport interface FrontmatterSplit {\n frontmatter: Record<string, unknown>;\n body: string;\n}\n\nexport function splitFrontmatter(raw: string): FrontmatterSplit {\n // Normalize newlines so Windows-style files don't break the split.\n const text = raw.replace(/\\r\\n/g, \"\\n\").replace(/^/, \"\");\n const lines = text.split(\"\\n\");\n\n // First non-empty line must be `---`.\n let i = 0;\n while (i < lines.length && lines[i].trim() === \"\") i++;\n if (i >= lines.length || lines[i].trim() !== FRONTMATTER_FENCE) {\n throw new Error(\"artifact missing leading `---` frontmatter fence\");\n }\n const startLine = i + 1;\n\n // Find closing fence.\n let endLine = -1;\n for (let j = startLine; j < lines.length; j++) {\n if (lines[j].trim() === FRONTMATTER_FENCE) {\n endLine = j;\n break;\n }\n }\n if (endLine === -1) {\n throw new Error(\"artifact missing closing `---` frontmatter fence\");\n }\n\n const frontmatterText = lines.slice(startLine, endLine).join(\"\\n\");\n const body = lines.slice(endLine + 1).join(\"\\n\").replace(/^\\n+/, \"\");\n\n let frontmatter: unknown;\n try {\n frontmatter = frontmatterText.trim().length === 0 ? {} : yamlParse(frontmatterText);\n } catch (err) {\n throw new Error(`frontmatter YAML parse error: ${(err as Error).message}`);\n }\n if (frontmatter === null || typeof frontmatter !== \"object\" || Array.isArray(frontmatter)) {\n throw new Error(\"frontmatter must be a YAML mapping\");\n }\n return { frontmatter: frontmatter as Record<string, unknown>, body };\n}\n\n/** Internal: render YAML for embedding inside a fenced block. */\nfunction dumpYaml(value: unknown): string {\n // `lineWidth: 0` keeps long lines unwrapped (better for round-trip stability).\n return yamlStringify(value, { indent: 2, lineWidth: 0 });\n}\n\n// ---------- DESIGN ----------\n\n/**\n * Parse a DESIGN.md raw string into a validated `DesignArtifact`. The body\n * is carried verbatim (no further structural lifting).\n */\nexport function parseDesign(raw: string): DesignArtifact {\n const { frontmatter, body } = splitFrontmatter(raw);\n return DesignArtifactSchema.parse({ ...frontmatter, body });\n}\n\n/** Serialize a DesignArtifact to a canonical Markdown-with-frontmatter string. */\nexport function serializeDesign(artifact: DesignArtifact): string {\n const { body, ...frontmatter } = artifact;\n return `---\\n${dumpYaml(frontmatter)}---\\n\\n${body}`;\n}\n\n// ---------- SCRIPT ----------\n\n/**\n * Extract beat lists from a SCRIPT body.\n *\n * The body uses `# Hook | # Story | # Proof | # CTA` H1 headings for\n * narrated mode, with each section containing a YAML-list of beat\n * mappings. For carousel / text-only modes, the body is a single YAML\n * list (no headings required) — but we also accept a `# Beats` heading\n * for symmetry.\n *\n * NOTE on idiom choice: we elected to put beats in the body (per the\n * spec's EXAMPLE) rather than in frontmatter — it diffs better when a\n * creator edits a single beat, which is the load-bearing re-entry move\n * (spec §7).\n */\nconst NARRATED_SECTION_HEADERS: Record<string, \"hook\" | \"story\" | \"proof\" | \"cta\"> = {\n hook: \"hook\",\n story: \"story\",\n proof: \"proof\",\n cta: \"cta\",\n};\n\ninterface ParsedScriptBody {\n blocks?: { hook: unknown[]; story: unknown[]; proof: unknown[]; cta: unknown[] };\n beats?: unknown[];\n remainder: string;\n}\n\nfunction parseScriptBody(body: string, mode: string): ParsedScriptBody {\n const text = body.replace(/\\r\\n/g, \"\\n\");\n const lines = text.split(\"\\n\");\n\n if (mode === \"narrated\") {\n const blocks: { hook: unknown[]; story: unknown[]; proof: unknown[]; cta: unknown[] } = {\n hook: [], story: [], proof: [], cta: [],\n };\n let currentKey: \"hook\" | \"story\" | \"proof\" | \"cta\" | null = null;\n let buffer: string[] = [];\n const remainder: string[] = [];\n\n const flush = () => {\n if (currentKey === null) return;\n const yamlText = buffer.join(\"\\n\").trim();\n if (yamlText.length === 0) return;\n const parsed = yamlParse(yamlText);\n if (!Array.isArray(parsed)) {\n throw new Error(`SCRIPT section \"${currentKey}\" must be a YAML list of beats`);\n }\n blocks[currentKey] = parsed;\n };\n\n for (const line of lines) {\n const headingMatch = /^#\\s+(.+?)\\s*$/.exec(line);\n if (headingMatch) {\n const key = headingMatch[1].toLowerCase();\n if (key in NARRATED_SECTION_HEADERS) {\n flush();\n currentKey = NARRATED_SECTION_HEADERS[key];\n buffer = [];\n continue;\n }\n }\n if (currentKey === null) {\n remainder.push(line);\n } else {\n buffer.push(line);\n }\n }\n flush();\n return { blocks, remainder: remainder.join(\"\\n\").trim() };\n }\n\n // carousel / text-only — single YAML list, optionally under `# Beats`.\n const beatLines: string[] = [];\n const remainder: string[] = [];\n let inBeats = false;\n let sawAnyHeading = false;\n for (const line of lines) {\n const headingMatch = /^#\\s+(.+?)\\s*$/.exec(line);\n if (headingMatch) {\n sawAnyHeading = true;\n inBeats = headingMatch[1].toLowerCase() === \"beats\";\n continue;\n }\n if (sawAnyHeading) {\n if (inBeats) beatLines.push(line);\n else remainder.push(line);\n } else {\n beatLines.push(line);\n }\n }\n const yamlText = beatLines.join(\"\\n\").trim();\n let beats: unknown[] = [];\n if (yamlText.length > 0) {\n const parsed = yamlParse(yamlText);\n if (!Array.isArray(parsed)) {\n throw new Error(`SCRIPT body must be a YAML list of beats (mode: ${mode})`);\n }\n beats = parsed;\n }\n return { beats, remainder: remainder.join(\"\\n\").trim() };\n}\n\n/** Parse a SCRIPT.md raw string into a validated `ScriptArtifact`. */\nexport function parseScript(raw: string): ScriptArtifact {\n const { frontmatter, body } = splitFrontmatter(raw);\n const mode = (frontmatter as { mode?: unknown }).mode;\n if (mode !== \"narrated\" && mode !== \"carousel\" && mode !== \"text-only\") {\n throw new Error(`SCRIPT frontmatter \"mode\" must be one of narrated | carousel | text-only (got ${JSON.stringify(mode)})`);\n }\n const parsed = parseScriptBody(body, mode);\n\n const assembled: Record<string, unknown> = { ...frontmatter, body: parsed.remainder };\n if (mode === \"narrated\") {\n assembled.blocks = parsed.blocks;\n } else {\n assembled.beats = parsed.beats;\n }\n return ScriptArtifactSchema.parse(assembled);\n}\n\n/** Serialize a ScriptArtifact to a canonical Markdown-with-frontmatter string. */\nexport function serializeScript(artifact: ScriptArtifact): string {\n if (artifact.mode === \"narrated\") {\n // Validate-and-strip default-bearing fields via the per-beat schema so\n // round-trip stays canonical (bind_to_transcript defaults to true).\n const { mode, target_duration_s, language, tts_voice, blocks, body } = artifact;\n const fm: Record<string, unknown> = { mode, target_duration_s, language };\n if (tts_voice !== undefined) fm.tts_voice = tts_voice;\n const sectionDump = (key: \"Hook\" | \"Story\" | \"Proof\" | \"CTA\", beats: unknown[]) =>\n `# ${key}\\n${dumpYaml(beats).trimEnd()}\\n`;\n const sections = [\n sectionDump(\"Hook\", blocks.hook),\n sectionDump(\"Story\", blocks.story),\n sectionDump(\"Proof\", blocks.proof),\n sectionDump(\"CTA\", blocks.cta),\n ].join(\"\\n\");\n const trailingBody = body.trim().length > 0 ? `\\n${body.trim()}\\n` : \"\";\n return `---\\n${dumpYaml(fm)}---\\n\\n${sections}${trailingBody}`;\n }\n const { mode, target_duration_s, language, tts_voice, beats, body } = artifact;\n const fm: Record<string, unknown> = { mode, target_duration_s, language };\n if (tts_voice !== undefined) fm.tts_voice = tts_voice;\n const trailingBody = body.trim().length > 0 ? `\\n${body.trim()}\\n` : \"\";\n return `---\\n${dumpYaml(fm)}---\\n\\n# Beats\\n${dumpYaml(beats).trimEnd()}\\n${trailingBody}`;\n}\n\n/** Re-export — useful for fixture builders that want to validate piecewise. */\nexport { NarratedBeatSchema, NonNarratedBeatSchema, NarratedScriptSchema };\n\n// ---------- STORYBOARD ----------\n\n/**\n * Extract a STORYBOARD body into a list of beats. Each beat is a `## <id>`\n * heading followed by a YAML mapping block (lines until the next `##`).\n */\nfunction parseStoryboardBody(body: string): unknown[] {\n const text = body.replace(/\\r\\n/g, \"\\n\");\n const lines = text.split(\"\\n\");\n\n type Pending = { id: string; buffer: string[] };\n const beats: Pending[] = [];\n let current: Pending | null = null;\n\n for (const line of lines) {\n const headingMatch = /^##\\s+(.+?)\\s*$/.exec(line);\n if (headingMatch) {\n if (current !== null) beats.push(current);\n current = { id: headingMatch[1].trim(), buffer: [] };\n continue;\n }\n if (current !== null) {\n current.buffer.push(line);\n }\n }\n if (current !== null) beats.push(current);\n\n return beats.map(({ id, buffer }) => {\n const yamlText = buffer.join(\"\\n\").trim();\n if (yamlText.length === 0) {\n return { id };\n }\n const parsed = yamlParse(yamlText);\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(`STORYBOARD beat \"${id}\" body must be a YAML mapping`);\n }\n return { id, ...(parsed as Record<string, unknown>) };\n });\n}\n\n/** Parse a STORYBOARD.md raw string into a validated `StoryboardArtifact`. */\nexport function parseStoryboard(raw: string): StoryboardArtifact {\n const { frontmatter, body } = splitFrontmatter(raw);\n const beats = parseStoryboardBody(body);\n return StoryboardArtifactSchema.parse({ ...frontmatter, beats });\n}\n\n/** Serialize a StoryboardArtifact to a canonical Markdown-with-frontmatter string. */\nexport function serializeStoryboard(artifact: StoryboardArtifact): string {\n const { technique_library_version, aspect_ratio, beats } = artifact;\n const fm = { technique_library_version, aspect_ratio };\n const beatBlocks = beats.map((beat) => {\n const { id, ...rest } = beat;\n return `## ${id}\\n${dumpYaml(rest).trimEnd()}\\n`;\n }).join(\"\\n\");\n return `---\\n${dumpYaml(fm)}---\\n\\n${beatBlocks}`;\n}\n","import type { DesignArtifact } from \"./design.js\";\nimport { allScriptBeats, type ScriptArtifact } from \"./script.js\";\nimport { isBRollBeatId, type StoryboardArtifact } from \"./storyboard.js\";\nimport { parseSlotRef, SLOT_KINDS } from \"./slot.js\";\nimport { getTechniqueLibrary } from \"./technique.js\";\n\n/**\n * Cross-artifact validation result.\n *\n * NOTE: this return shape (`{ ok, warnings, errors }`) is intentionally\n * DIFFERENT from the recipe-package's `{ success, warnings? }` idiom.\n * The artifacts surface validates multiple independent rules whose\n * severities differ (some are warn-only pre-VO, others are hard fails)\n * — flattening to a single discriminated result loses that.\n */\nexport interface ArtifactSetValidationResult {\n ok: boolean;\n warnings: string[];\n errors: string[];\n}\n\nexport interface ArtifactSet {\n design?: DesignArtifact;\n script?: ScriptArtifact;\n storyboard?: StoryboardArtifact;\n}\n\n/**\n * Run cross-artifact validation:\n * 1. Every STORYBOARD beat id must match a SCRIPT beat id, UNLESS the\n * storyboard id is prefixed `b-roll.` (exemption per task spec).\n * 2. Every slot reference (in storyboard beats and sfx entries) parses\n * to `<kind>.<category>.<specifier>` and uses a known kind.\n * 3. Every storyboard technique exists in the active technique library\n * (resolved by `technique_library_version`).\n * 4. Sum of script beat `est_duration_s` ≤ `target_duration_s`\n * (WARN-ONLY pre-VO; the Iris pipeline will hard-fail post-transcript\n * binding — that's later code, not this validator's job).\n *\n * This function never throws — callers decide what to do with `ok`.\n */\nexport function validateArtifactSet(set: ArtifactSet): ArtifactSetValidationResult {\n const warnings: string[] = [];\n const errors: string[] = [];\n\n // --- (1) Beat-id matching between STORYBOARD and SCRIPT ---\n if (set.storyboard && set.script) {\n const scriptIds = new Set(allScriptBeats(set.script).map((b) => b.id));\n for (const beat of set.storyboard.beats) {\n if (isBRollBeatId(beat.id)) continue;\n if (!scriptIds.has(beat.id)) {\n errors.push(\n `STORYBOARD beat \"${beat.id}\" has no matching SCRIPT beat (and is not prefixed b-roll.)`,\n );\n }\n }\n }\n\n // --- (2) Slot reference validity ---\n if (set.storyboard) {\n for (const beat of set.storyboard.beats) {\n for (const slot of beat.slots) {\n const parsed = parseSlotRef(slot);\n if (parsed === null) {\n errors.push(\n `STORYBOARD beat \"${beat.id}\" slot \"${slot}\" is malformed or has an unknown kind (expected one of ${SLOT_KINDS.join(\", \")})`,\n );\n }\n }\n if (beat.sfx) {\n for (const sfx of beat.sfx) {\n const parsed = parseSlotRef(sfx.slot);\n if (parsed === null) {\n errors.push(\n `STORYBOARD beat \"${beat.id}\" sfx slot \"${sfx.slot}\" is malformed or has an unknown kind`,\n );\n }\n }\n }\n }\n }\n\n // --- (3) Technique library membership ---\n if (set.storyboard) {\n const lib = getTechniqueLibrary(set.storyboard.technique_library_version);\n if (lib === null) {\n errors.push(\n `STORYBOARD references unknown technique_library_version ${set.storyboard.technique_library_version}`,\n );\n } else {\n const known = new Set(lib.techniques);\n for (const beat of set.storyboard.beats) {\n for (const t of beat.techniques) {\n if (!known.has(t)) {\n errors.push(\n `STORYBOARD beat \"${beat.id}\" uses unknown technique \"${t}\" (technique_library_version=${lib.version})`,\n );\n }\n }\n }\n }\n }\n\n // --- (4) Duration sum (WARN-ONLY pre-VO) ---\n if (set.script) {\n const sum = allScriptBeats(set.script).reduce((acc, b) => acc + b.est_duration_s, 0);\n if (sum > set.script.target_duration_s) {\n warnings.push(\n `SCRIPT beat est_duration_s sum (${sum.toFixed(2)}s) exceeds target_duration_s (${set.script.target_duration_s}s) — warn only pre-VO; will hard-fail post-transcript binding`,\n );\n }\n }\n\n return { ok: errors.length === 0, warnings, errors };\n}\n","import { z } from \"zod\";\n\n/**\n * Workspace manifest schema — the YAML-serialized contents of\n * `workspace.atelier` at the root of an Atelier workspace.\n *\n * A workspace is a layer above Project: a single directory holding multiple\n * content Projects with shared creator-level configuration (learning mode,\n * mind-map, recipes). The manifest itself stays tiny on purpose — most\n * workspace-level state lives in `.atelier/` siblings on disk, not in this\n * file. Fields listed here are the minimum needed to:\n * - discover the workspace from any descendant cwd (`workspace.atelier`\n * is the on-disk signal)\n * - propagate creator preferences into newly-init'd projects\n * (`default_mode`)\n * - hint which subdirs are Projects (`projects?`); on-disk truth is\n * authoritative — `projects` is advisory and may be refreshed by\n * scanning for `project.atelier` files.\n *\n * `workspace.atelier` is YAML (intentionally — distinguishes it from\n * `project.atelier` which is JSON) and shares the `.atelier` extension as\n * a family marker. The two never collide in a single directory.\n */\n\n/**\n * WorkspaceManifest — top-level. Strict on unknown keys; same posture as the\n * recipe schema so authoring typos surface at validate time rather than being\n * silently dropped.\n */\nexport const WorkspaceManifestSchema = z.object({\n /** Manifest schema version. Pinned to '1.0' for the initial release. */\n version: z.literal(\"1.0\"),\n /** Display name; defaults to the workspace dir basename at create time. */\n name: z.string().min(1),\n /** ISO 8601 timestamp set by the writer. */\n created: z.string().min(1),\n /**\n * Inherited by new projects created via `atelier init` inside this\n * workspace. The creator pre-declares the autonomy posture once at the\n * workspace level; per-project overrides still allowed via per-project\n * `.atelier/learning-mode.yaml` (writes always happen at workspace level\n * unless explicitly overridden).\n */\n default_mode: z.enum([\"ambient\", \"explicit\"]),\n /**\n * Relative paths (single-segment subdir names) of known Projects inside\n * the workspace. Advisory only — on-disk `project.atelier` presence is\n * authoritative. Refresh via `listProjects(workspaceDir)`.\n */\n projects: z.array(z.string().min(1)).optional(),\n /** Free-text creator description. Optional. */\n description: z.string().optional(),\n}).strict();\n\n/** Inferred TS type for the manifest. */\nexport type WorkspaceManifest = z.infer<typeof WorkspaceManifestSchema>;\n","// MediaNotes — sidecar notes for a media file.\n//\n// Lives at `<media-file>.notes.md` next to every media file in a Project's\n// `media/` directory. Structured YAML frontmatter (constraints + tags) plus a\n// freeform Markdown body with conventional per-author headings (Lux notes,\n// Quill notes, Iris notes, Creator notes). Inert artifact — pure data, no\n// executables, no upload paths (TD-229, TD-271).\n//\n// The frontmatter is the contract Lux/Iris/Quill honor at slot-binding time:\n// - constraints.do_not[] — non-negotiable exclusions\n// - constraints.prefer_for[] — soft preference signals\n// - tags[] — free-form labels the mind-map / scorer reads\n//\n// The body is the conversation log between the creator and the agent team.\n// Each author appends to their own section (sentinel headings); idempotent\n// replacement keeps the file readable across many sessions.\n\nimport { z } from \"zod\";\n\n/**\n * Free-form string list that may not contain blank entries — used for tags,\n * do_not, and prefer_for. Empties are dropped at parse time so a forgotten\n * trailing dash in YAML doesn't break a build.\n */\nconst NonEmptyStringListSchema = z.array(z.string().min(1));\n\n/** Optional constraint sub-object on a notes frontmatter. */\nexport const MediaNotesConstraintsSchema = z.object({\n /**\n * Hard exclusions. Lux + Iris MUST refuse to bind this media to a slot if\n * any do_not rule applies (the rule is a free-text string the agent reads\n * with judgement — e.g. \"never use in a CTA beat\", \"no client logos\").\n */\n do_not: NonEmptyStringListSchema.optional(),\n /**\n * Soft preferences — weight up candidacy when these conditions hold. Same\n * free-text shape as do_not but the polarity is positive (\"good for hooks\",\n * \"prefer for warm tone\").\n */\n prefer_for: NonEmptyStringListSchema.optional(),\n}).strict();\n\nexport type MediaNotesConstraints = z.infer<typeof MediaNotesConstraintsSchema>;\n\n/**\n * Frontmatter shape — the typed half of a `<file>.notes.md`. Required fields\n * (file/added/added_by) are written by `scaffoldMediaNotes` at ingest time;\n * everything else accumulates over the life of the project.\n */\nexport const MediaNotesFrontmatterSchema = z.object({\n /** Basename of the media file this notes file sits next to. */\n file: z.string().min(1),\n /** ISO 8601 timestamp captured at ingest. */\n added: z.string().min(1),\n /** User identifier (env $USER at ingest, \"creator\" fallback). */\n added_by: z.string().min(1),\n /** Free-form labels. Empty by default; agents and creator both append. */\n tags: NonEmptyStringListSchema.default([]),\n /** Optional do_not / prefer_for object. Absent means \"no rules yet.\" */\n constraints: MediaNotesConstraintsSchema.optional(),\n}).strict();\n\nexport type MediaNotesFrontmatter = z.infer<typeof MediaNotesFrontmatterSchema>;\n\n/**\n * Whole-file shape — frontmatter plus the Markdown body. The body is parsed\n * as opaque text; the per-author section convention is enforced at write time\n * (via `appendNoteSection`) rather than at the schema level so creators can\n * freely edit the body without breaking validation.\n */\nexport const MediaNotesSchema = z.object({\n frontmatter: MediaNotesFrontmatterSchema,\n body: z.string(),\n}).strict();\n\nexport type MediaNotes = z.infer<typeof MediaNotesSchema>;\n\n/**\n * Closed enum of author identities recognized in per-section appends. Matches\n * the persona ids registered in `.paradigm/personas/index.yaml` (lux/quill/\n * iris) plus the `creator` self-author.\n */\nexport const MediaNotesAuthorSchema = z.enum([\"lux\", \"quill\", \"iris\", \"creator\"]);\nexport type MediaNotesAuthor = z.infer<typeof MediaNotesAuthorSchema>;\n\n/**\n * Stable per-author heading text — exported for the CLI/MCP writers so the\n * sentinel format never drifts. Format: `## <Name> notes (<role>?)` where the\n * \"(role)\" suffix matches the canonical persona file for the named persona.\n */\nexport const MEDIA_NOTES_HEADINGS: Record<MediaNotesAuthor, string> = {\n lux: \"## Lux notes (cinematographer)\",\n quill: \"## Quill notes (showrunner)\",\n iris: \"## Iris notes (composer)\",\n creator: \"## Creator notes\",\n};\n","// @a-company/atelier-mcp — Layer management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Layer, Visual, UnitValue } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\n/** Zod schema for visual objects passed by the AI */\nconst VisualInputSchema = z.object({\n type: z.enum([\"shape\", \"text\", \"image\", \"video\", \"audio\", \"group\", \"ref\"]).describe(\"Visual type\"),\n // shape visual fields\n shape: z.object({\n type: z.enum([\"rect\", \"ellipse\", \"path\"]),\n cornerRadius: z.union([z.number(), z.tuple([z.number(), z.number(), z.number(), z.number()])]).optional(),\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).optional(),\n closed: z.boolean().optional(),\n }).optional(),\n fill: z.record(z.unknown()).optional(),\n stroke: z.record(z.unknown()).optional(),\n // text visual fields\n content: z.string().optional(),\n style: z.record(z.unknown()).optional(),\n // image visual fields\n assetId: z.string().optional(),\n sourceRect: z.object({\n x: z.number(), y: z.number(), width: z.number().positive(), height: z.number().positive(),\n }).optional(),\n spritesheet: z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n }).optional(),\n frameIndex: z.number().int().min(0).optional(),\n // ref visual fields\n src: z.string().optional(),\n state: z.string().optional(),\n frame: z.number().int().min(0).optional(),\n // video / audio visual fields (v1.0+)\n startFrame: z.number().int().min(0).optional().describe(\"Video/audio: composition frame when playback begins\"),\n sourceOffset: z.number().min(0).optional().describe(\"Video/audio: seconds into source to begin playback\"),\n sourceEnd: z.number().positive().optional().describe(\"Video/audio: seconds of source to stop at\"),\n playbackRate: z.number().positive().optional().describe(\"Video/audio: playback speed multiplier\"),\n volume: z.number().min(0).max(1).optional().describe(\"Video/audio: volume 0–1\"),\n muted: z.boolean().optional().describe(\"Video/audio: mute\"),\n objectFit: z.enum([\"contain\", \"cover\", \"fill\"]).optional().describe(\"Video: fit mode\"),\n fadeIn: z.number().min(0).optional().describe(\"Audio: fade-in duration in seconds\"),\n fadeOut: z.number().min(0).optional().describe(\"Audio: fade-out duration in seconds\"),\n}).describe(\"Visual content definition\");\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_layer ───────────────────────────────────────\n server.tool(\n \"atelier_add_layer\",\n \"Add a new layer to an Atelier document\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Unique layer ID\"),\n visual: VisualInputSchema.describe(\"Visual content definition\"),\n x: z.union([z.number(), z.string()]).describe(\"X position (pixels or percentage)\"),\n y: z.union([z.number(), z.string()]).describe(\"Y position (pixels or percentage)\"),\n width: z.union([z.number(), z.string()]).describe(\"Width (pixels or percentage)\"),\n height: z.union([z.number(), z.string()]).describe(\"Height (pixels or percentage)\"),\n description: z.string().optional().describe(\"Layer description\"),\n tags: z.array(z.string()).optional().describe(\"Tags\"),\n opacity: z.number().min(0).max(1).optional().describe(\"Opacity 0-1\"),\n rotation: z.number().optional().describe(\"Rotation in degrees\"),\n parentId: z.string().optional().describe(\"Parent layer ID for transform inheritance\"),\n anchorPoint: z.object({ x: z.number(), y: z.number() }).optional().describe(\"Anchor point (0-1 normalized)\"),\n scale: z.object({ x: z.number(), y: z.number() }).optional().describe(\"Scale factors\"),\n visible: z.boolean().optional().describe(\"Whether layer is visible\"),\n tint: z.object({\n color: z.string().describe(\"Tint color (hex string)\"),\n amount: z.number().min(0).max(1).describe(\"Tint amount (0 = none, 1 = full)\"),\n }).optional().describe(\"Color tint overlay\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, visual, x, y, width, height, description, tags, opacity, rotation, parentId, anchorPoint, scale, visible, tint }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n // Check for duplicate layer ID\n if (doc.layers.some(l => l.id === layerId)) {\n return err(`Layer \"${layerId}\" already exists in document \"${id}\"`);\n }\n\n // Validate parentId if provided\n if (parentId && !doc.layers.some(l => l.id === parentId)) {\n return err(`Parent layer \"${parentId}\" not found`);\n }\n\n const layer: Layer = {\n id: layerId,\n visual: visual as unknown as Visual,\n frame: { x: x as UnitValue, y: y as UnitValue },\n bounds: { width: width as UnitValue, height: height as UnitValue },\n ...(description != null ? { description } : {}),\n ...(tags ? { tags } : {}),\n ...(opacity != null ? { opacity } : {}),\n ...(rotation != null ? { rotation } : {}),\n ...(parentId ? { parentId } : {}),\n ...(anchorPoint ? { anchorPoint } : {}),\n ...(scale ? { scale } : {}),\n ...(visible != null ? { visible } : {}),\n ...(tint ? { tint } : {}),\n };\n\n doc.layers.push(layer);\n return ok({ layerId, index: doc.layers.length - 1 });\n },\n );\n\n // ── atelier_edit_layer ──────────────────────────────────────\n server.tool(\n \"atelier_edit_layer\",\n \"Edit properties of an existing layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID to edit\"),\n x: z.union([z.number(), z.string()]).optional().describe(\"New X position\"),\n y: z.union([z.number(), z.string()]).optional().describe(\"New Y position\"),\n width: z.union([z.number(), z.string()]).optional().describe(\"New width\"),\n height: z.union([z.number(), z.string()]).optional().describe(\"New height\"),\n description: z.string().optional().describe(\"New description\"),\n tags: z.array(z.string()).optional().describe(\"New tags\"),\n opacity: z.number().min(0).max(1).optional().describe(\"New opacity\"),\n rotation: z.number().optional().describe(\"New rotation\"),\n parentId: z.string().nullable().optional().describe(\"New parent layer ID (null to clear)\"),\n anchorPoint: z.object({ x: z.number(), y: z.number() }).optional().describe(\"New anchor point\"),\n scale: z.object({ x: z.number(), y: z.number() }).optional().describe(\"New scale\"),\n visible: z.boolean().optional().describe(\"New visibility\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, x, y, width, height, description, tags, opacity, rotation, parentId, anchorPoint, scale, visible }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (x != null) layer.frame.x = x as UnitValue;\n if (y != null) layer.frame.y = y as UnitValue;\n if (width != null) layer.bounds.width = width as UnitValue;\n if (height != null) layer.bounds.height = height as UnitValue;\n if (description != null) layer.description = description;\n if (tags) layer.tags = tags;\n if (opacity != null) layer.opacity = opacity;\n if (rotation != null) layer.rotation = rotation;\n if (parentId !== undefined) {\n if (parentId === null) {\n delete layer.parentId;\n } else {\n if (!doc.layers.some(l => l.id === parentId)) return err(`Parent layer \"${parentId}\" not found`);\n layer.parentId = parentId;\n }\n }\n if (anchorPoint) layer.anchorPoint = anchorPoint;\n if (scale) layer.scale = scale;\n if (visible != null) layer.visible = visible;\n\n return ok({ layerId, updated: true });\n },\n );\n\n // ── atelier_remove_layer ────────────────────────────────────\n server.tool(\n \"atelier_remove_layer\",\n \"Remove a layer from an Atelier document\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, layerId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const index = doc.layers.findIndex(l => l.id === layerId);\n if (index === -1) return err(`Layer \"${layerId}\" not found`);\n\n // Check for deltas that reference this layer\n const warnings: string[] = [];\n for (const [stateName, state] of Object.entries(doc.states)) {\n const deltaCount = state.deltas.filter(d => d.layer === layerId).length;\n if (deltaCount > 0) {\n warnings.push(`State \"${stateName}\" has ${deltaCount} delta(s) referencing this layer`);\n }\n }\n\n // Check for child layers\n const childCount = doc.layers.filter(l => l.parentId === layerId).length;\n if (childCount > 0) {\n warnings.push(`${childCount} child layer(s) reference this layer as parent`);\n }\n\n doc.layers.splice(index, 1);\n return ok({ layerId, removed: true, warnings });\n },\n );\n\n // ── atelier_list_layers ─────────────────────────────────────\n server.tool(\n \"atelier_list_layers\",\n \"List all layers in an Atelier document\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layers = doc.layers.map((l, index) => ({\n index,\n id: l.id,\n type: l.visual.type,\n frame: l.frame,\n bounds: l.bounds,\n description: l.description,\n tags: l.tags,\n opacity: l.opacity,\n rotation: l.rotation,\n parentId: l.parentId,\n visible: l.visible,\n }));\n\n return ok({ layers, count: layers.length });\n },\n );\n\n // ── atelier_reorder ─────────────────────────────────────────\n server.tool(\n \"atelier_reorder\",\n \"Move a layer to a new position in the layer stack\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID to move\"),\n position: z.number().int().min(0).describe(\"Target position index (0-based)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, position }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const currentIndex = doc.layers.findIndex(l => l.id === layerId);\n if (currentIndex === -1) return err(`Layer \"${layerId}\" not found`);\n\n const targetPos = Math.min(position, doc.layers.length - 1);\n const [layer] = doc.layers.splice(currentIndex, 1);\n doc.layers.splice(targetPos, 0, layer);\n\n return ok({ layerId, from: currentIndex, to: targetPos });\n },\n );\n}\n","// @a-company/atelier-mcp — Shape, fill, and stroke tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, ShapeVisual } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_set_shape ───────────────────────────────────────\n server.tool(\n \"atelier_set_shape\",\n \"Set the shape on a shape-type layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID (must be a shape visual)\"),\n shape: z.object({\n type: z.enum([\"rect\", \"ellipse\", \"path\"]).describe(\"Shape type\"),\n cornerRadius: z.union([\n z.number(),\n z.tuple([z.number(), z.number(), z.number(), z.number()]),\n ]).optional().describe(\"Corner radius (rect only)\"),\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).optional().describe(\"Path points (path only)\"),\n closed: z.boolean().optional().describe(\"Whether path is closed (path only)\"),\n }).describe(\"Shape definition\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, shape }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"shape\") return err(`Layer \"${layerId}\" is type \"${layer.visual.type}\", not \"shape\"`);\n\n (layer.visual as ShapeVisual).shape = shape as ShapeVisual[\"shape\"];\n return ok({ layerId, shape: shape.type });\n },\n );\n\n // ── atelier_set_fill ────────────────────────────────────────\n server.tool(\n \"atelier_set_fill\",\n \"Set the fill on a shape-type layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID (must be a shape visual)\"),\n fill: z.object({\n type: z.enum([\"solid\", \"linear-gradient\", \"radial-gradient\"]).describe(\"Fill type\"),\n color: z.unknown().optional().describe(\"Color for solid fill (hex string or RGBA/HSLA object)\"),\n angle: z.number().optional().describe(\"Angle in degrees (linear-gradient only)\"),\n center: z.object({\n x: z.union([z.number(), z.string()]),\n y: z.union([z.number(), z.string()]),\n }).optional().describe(\"Center point (radial-gradient only)\"),\n radius: z.union([z.number(), z.string()]).optional().describe(\"Radius (radial-gradient only)\"),\n stops: z.array(z.object({\n offset: z.number().min(0).max(1),\n color: z.unknown(),\n })).optional().describe(\"Gradient stops\"),\n }).describe(\"Fill definition\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, fill }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"shape\") return err(`Layer \"${layerId}\" is type \"${layer.visual.type}\", not \"shape\"`);\n\n (layer.visual as ShapeVisual).fill = fill as unknown as ShapeVisual[\"fill\"];\n return ok({ layerId, fillType: fill.type });\n },\n );\n\n // ── atelier_set_stroke ──────────────────────────────────────\n server.tool(\n \"atelier_set_stroke\",\n \"Set the stroke on a shape-type layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID (must be a shape visual)\"),\n stroke: z.object({\n color: z.unknown().describe(\"Stroke color (hex string or RGBA/HSLA object)\"),\n width: z.number().positive().describe(\"Stroke width in pixels\"),\n dash: z.array(z.number()).optional().describe(\"Dash pattern\"),\n lineCap: z.enum([\"butt\", \"round\", \"square\"]).optional().describe(\"Line cap style\"),\n lineJoin: z.enum([\"miter\", \"round\", \"bevel\"]).optional().describe(\"Line join style\"),\n }).describe(\"Stroke definition\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, stroke }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"shape\") return err(`Layer \"${layerId}\" is type \"${layer.visual.type}\", not \"shape\"`);\n\n (layer.visual as ShapeVisual).stroke = stroke as unknown as ShapeVisual[\"stroke\"];\n return ok({ layerId, strokeWidth: stroke.width });\n },\n );\n}\n","// @a-company/atelier-mcp — State management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_state ───────────────────────────────────────\n server.tool(\n \"atelier_add_state\",\n \"Add a named animation state to a document\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name (e.g. 'intro', 'hover', 'exit')\"),\n duration: z.number().positive().int().describe(\"Duration in frames\"),\n description: z.string().optional().describe(\"State description\"),\n tags: z.array(z.string()).optional().describe(\"Tags\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, duration, description, tags }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (doc.states[stateName]) {\n return err(`State \"${stateName}\" already exists`);\n }\n\n doc.states[stateName] = {\n duration,\n deltas: [],\n ...(description ? { description } : {}),\n ...(tags ? { tags } : {}),\n };\n\n return ok({ stateName, duration });\n },\n );\n\n // ── atelier_edit_state ──────────────────────────────────────\n server.tool(\n \"atelier_edit_state\",\n \"Edit metadata of an existing animation state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to edit\"),\n duration: z.number().positive().int().optional().describe(\"New duration in frames\"),\n description: z.string().optional().describe(\"New description\"),\n tags: z.array(z.string()).optional().describe(\"New tags\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, duration, description, tags }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (duration != null) state.duration = duration;\n if (description != null) state.description = description;\n if (tags) state.tags = tags;\n\n return ok({ stateName, updated: true });\n },\n );\n\n // ── atelier_remove_state ────────────────────────────────────\n server.tool(\n \"atelier_remove_state\",\n \"Remove an animation state and all its deltas\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, stateName }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) return err(`State \"${stateName}\" not found`);\n\n const deltaCount = doc.states[stateName].deltas.length;\n delete doc.states[stateName];\n\n return ok({ stateName, removed: true, deltasRemoved: deltaCount });\n },\n );\n\n // ── atelier_list_states ─────────────────────────────────────\n server.tool(\n \"atelier_list_states\",\n \"List all animation states in a document\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const states = Object.entries(doc.states).map(([name, state]) => ({\n name,\n duration: state.duration,\n description: state.description,\n tags: state.tags,\n deltaCount: state.deltas.length,\n }));\n\n return ok({ states, count: states.length });\n },\n );\n}\n","// @a-company/atelier-mcp — Delta (animation keyframe) tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Delta, AnimatableProperty, Easing } from \"@a-company/atelier-types\";\nimport { AnimatablePropertySchema, EasingSchema } from \"@a-company/atelier-schema\";\nimport { validateNoOverlap, expandPreset } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\n// Canonical source: @a-company/atelier-schema — single source of truth for AnimatableProperty\nconst AnimatablePropertyEnum = AnimatablePropertySchema;\nconst EasingInputSchema = EasingSchema.describe(\"Easing function\");\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_delta ───────────────────────────────────────\n server.tool(\n \"atelier_add_delta\",\n \"Add an animation delta (keyframe transition) to a state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n layer: z.string().describe(\"Target layer ID\"),\n property: AnimatablePropertyEnum.describe(\"Property to animate\"),\n range: z.tuple([z.number().int().min(0), z.number().int().min(0)]).describe(\"Frame range [start, end] inclusive\"),\n from: z.unknown().describe(\"Starting value\"),\n to: z.unknown().describe(\"Ending value\"),\n easing: EasingInputSchema.optional().describe(\"Easing function\"),\n description: z.string().optional().describe(\"Delta description\"),\n tags: z.array(z.string()).optional().describe(\"Tags\"),\n deltaId: z.string().optional().describe(\"Custom delta ID\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, layer, property, range, from, to, easing, description, tags, deltaId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n // Validate state exists\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n // Validate layer exists\n if (!doc.layers.some(l => l.id === layer)) {\n return err(`Layer \"${layer}\" not found`);\n }\n\n // Validate range\n if (range[0] > range[1]) {\n return err(`Invalid range: start (${range[0]}) must be <= end (${range[1]})`);\n }\n\n const delta: Delta = {\n layer,\n property: property as AnimatableProperty,\n range: [range[0], range[1]],\n from,\n to,\n ...(easing ? { easing: easing as Easing } : {}),\n ...(description ? { description } : {}),\n ...(tags ? { tags } : {}),\n ...(deltaId ? { id: deltaId } : {}),\n };\n\n // Check for overlaps\n const overlap = validateNoOverlap(state.deltas, delta);\n if (overlap) {\n return err(overlap.message);\n }\n\n state.deltas.push(delta);\n return ok({ stateName, deltaIndex: state.deltas.length - 1, layer, property });\n },\n );\n\n // ── atelier_edit_delta ──────────────────────────────────────\n server.tool(\n \"atelier_edit_delta\",\n \"Edit an existing delta by index within a state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n deltaIndex: z.number().int().min(0).describe(\"Delta index within the state\"),\n layer: z.string().optional().describe(\"New target layer ID\"),\n property: AnimatablePropertyEnum.optional().describe(\"New property to animate\"),\n range: z.tuple([z.number().int().min(0), z.number().int().min(0)]).optional().describe(\"New frame range [start, end]\"),\n from: z.unknown().optional().describe(\"New starting value\"),\n to: z.unknown().optional().describe(\"New ending value\"),\n easing: EasingInputSchema.optional().describe(\"New easing function\"),\n description: z.string().optional().describe(\"New description\"),\n tags: z.array(z.string()).optional().describe(\"New tags\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, deltaIndex, layer, property, range, from, to, easing, description, tags }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (deltaIndex >= state.deltas.length) {\n return err(`Delta index ${deltaIndex} out of range (${state.deltas.length} deltas)`);\n }\n\n const delta = state.deltas[deltaIndex];\n\n // Apply updates\n if (layer != null) {\n if (!doc.layers.some(l => l.id === layer)) return err(`Layer \"${layer}\" not found`);\n delta.layer = layer;\n }\n if (property != null) delta.property = property as AnimatableProperty;\n if (range != null) {\n if (range[0] > range[1]) return err(`Invalid range: start (${range[0]}) must be <= end (${range[1]})`);\n delta.range = [range[0], range[1]];\n }\n if (from !== undefined) delta.from = from;\n if (to !== undefined) delta.to = to;\n if (easing != null) delta.easing = easing as Easing;\n if (description != null) delta.description = description;\n if (tags) delta.tags = tags;\n\n // Re-validate overlaps with the updated delta against others\n const others = state.deltas.filter((_, i) => i !== deltaIndex);\n const overlap = validateNoOverlap(others, delta);\n if (overlap) {\n return err(`Edit would cause overlap: ${overlap.message}`);\n }\n\n return ok({ stateName, deltaIndex, updated: true });\n },\n );\n\n // ── atelier_remove_delta ────────────────────────────────────\n server.tool(\n \"atelier_remove_delta\",\n \"Remove a delta by index from a state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n deltaIndex: z.number().int().min(0).describe(\"Delta index to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, stateName, deltaIndex }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (deltaIndex >= state.deltas.length) {\n return err(`Delta index ${deltaIndex} out of range (${state.deltas.length} deltas)`);\n }\n\n const removed = state.deltas.splice(deltaIndex, 1)[0];\n return ok({\n stateName,\n removed: {\n layer: removed.layer,\n property: removed.property,\n range: removed.range,\n },\n remainingDeltas: state.deltas.length,\n });\n },\n );\n\n // ── atelier_apply_preset ────────────────────────────────────\n server.tool(\n \"atelier_apply_preset\",\n \"Apply a preset to a layer, expanding it into concrete deltas\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to add deltas to\"),\n presetName: z.string().describe(\"Preset name defined in the document\"),\n layerId: z.string().describe(\"Target layer ID\"),\n startFrame: z.number().int().min(0).optional().describe(\"Start frame (default: 0)\"),\n duration: z.number().positive().int().optional().describe(\"Duration for preset (default: state duration)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, presetName, layerId, startFrame, duration }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (!doc.layers.some(l => l.id === layerId)) {\n return err(`Layer \"${layerId}\" not found`);\n }\n\n if (!doc.presets || !doc.presets[presetName]) {\n return err(`Preset \"${presetName}\" not found`);\n }\n\n const preset = doc.presets[presetName];\n const start = startFrame ?? 0;\n const dur = duration ?? state.duration;\n\n const deltas = expandPreset(preset, layerId, start, dur);\n\n // Validate no overlaps for each new delta\n const errors: string[] = [];\n for (const delta of deltas) {\n const overlap = validateNoOverlap(state.deltas, delta);\n if (overlap) {\n errors.push(overlap.message);\n }\n }\n\n if (errors.length > 0) {\n return err(`Preset would cause overlaps:\\n${errors.join(\"\\n\")}`);\n }\n\n // Add all deltas\n state.deltas.push(...deltas);\n\n return ok({\n stateName,\n presetName,\n layerId,\n deltasAdded: deltas.length,\n totalDeltas: state.deltas.length,\n });\n },\n );\n}\n","/**\n * Linear easing — no acceleration.\n */\nexport function linear(t: number): number {\n return t;\n}\n\n/**\n * Cubic bezier easing — CSS-compatible.\n * Implements the same algorithm as CSS cubic-bezier().\n * @param x1 - first control point x\n * @param y1 - first control point y\n * @param x2 - second control point x\n * @param y2 - second control point y\n */\nexport function cubicBezier(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n): (t: number) => number {\n // Use binary search to find the parametric t value that gives us our x,\n // then compute the corresponding y. This is the standard algorithm used\n // by browsers for CSS transitions.\n\n return (t: number): number => {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n\n // Binary search for the parametric t value that gives us our x\n let lo = 0;\n let hi = 1;\n let mid: number = 0;\n\n for (let i = 0; i < 20; i++) {\n mid = (lo + hi) / 2;\n const x = sampleBezier(x1, x2, mid);\n if (Math.abs(x - t) < 1e-6) break;\n if (x < t) lo = mid;\n else hi = mid;\n }\n\n mid = (lo + hi) / 2;\n return sampleBezier(y1, y2, mid);\n };\n}\n\n/** Sample a single axis of a cubic bezier at parametric t */\nfunction sampleBezier(p1: number, p2: number, t: number): number {\n // B(t) = 3(1-t)^2*t*p1 + 3(1-t)*t^2*p2 + t^3\n return 3 * (1 - t) * (1 - t) * t * p1 + 3 * (1 - t) * t * t * p2 + t * t * t;\n}\n\n/** Common CSS easing presets */\nexport const easeIn = cubicBezier(0.42, 0, 1, 1);\nexport const easeOut = cubicBezier(0, 0, 0.58, 1);\nexport const easeInOut = cubicBezier(0.42, 0, 0.58, 1);\n\n/**\n * Step easing — jumps between discrete values.\n * @param steps - number of steps\n * @param position - \"start\" or \"end\" (default \"end\")\n */\nexport function step(\n steps: number,\n position: \"start\" | \"end\" = \"end\",\n): (t: number) => number {\n return (t: number): number => {\n if (t <= 0) return position === \"start\" ? 1 / steps : 0;\n if (t >= 1) return 1;\n\n const s = Math.floor(t * steps);\n if (position === \"start\") {\n return Math.min((s + 1) / steps, 1);\n }\n return s / steps;\n };\n}\n","export interface SpringConfig {\n mass?: number; // default 1\n stiffness?: number; // default 100\n damping?: number; // default 10\n velocity?: number; // default 0\n}\n\n/**\n * Creates a spring easing function.\n * Uses damped harmonic oscillator physics.\n * Returns a function that takes t (0-1) and returns the spring value.\n *\n * The spring always goes from 0 to 1, but may overshoot.\n */\nexport function spring(config: SpringConfig = {}): (t: number) => number {\n const {\n mass = 1,\n stiffness = 100,\n damping = 10,\n velocity = 0,\n } = config;\n\n const w0 = Math.sqrt(stiffness / mass); // natural frequency\n const zeta = damping / (2 * Math.sqrt(stiffness * mass)); // damping ratio\n\n // Determine total duration to normalize t\n // We pre-calculate a reasonable duration where the spring settles\n const duration = estimateSettleTime(zeta, w0);\n\n return (t: number): number => {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n\n const time = t * duration;\n let value: number;\n\n if (zeta < 1) {\n // Underdamped\n const wd = w0 * Math.sqrt(1 - zeta * zeta);\n const A = 1;\n const B = (zeta * w0 + velocity) / wd;\n value =\n 1 -\n Math.exp(-zeta * w0 * time) *\n (A * Math.cos(wd * time) + B * Math.sin(wd * time));\n } else if (zeta === 1) {\n // Critically damped\n value = 1 - Math.exp(-w0 * time) * (1 + (w0 + velocity) * time);\n } else {\n // Overdamped\n const s1 = -w0 * (zeta - Math.sqrt(zeta * zeta - 1));\n const s2 = -w0 * (zeta + Math.sqrt(zeta * zeta - 1));\n const A = (velocity - s2) / (s1 - s2);\n const B = 1 - A;\n value = 1 - A * Math.exp(s1 * time) - B * Math.exp(s2 * time);\n }\n\n return value;\n };\n}\n\n/**\n * Estimates the time for a spring to settle within 0.1% of target.\n */\nfunction estimateSettleTime(zeta: number, w0: number): number {\n if (zeta >= 1) {\n return 10 / (zeta * w0);\n }\n // For underdamped: settling ~ -ln(0.001) / (zeta * w0)\n return Math.log(1000) / (zeta * w0);\n}\n","/**\n * Linear interpolation between two numbers.\n */\nexport function lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\n/**\n * Clamp a value between min and max.\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Interpolate between two multi-dimensional values.\n * Arrays must be the same length.\n */\nexport function lerpArray(a: number[], b: number[], t: number): number[] {\n return a.map((v, i) => lerp(v, b[i], t));\n}\n\n/**\n * Re-maps a value from one range to another.\n */\nexport function remap(\n value: number,\n inMin: number,\n inMax: number,\n outMin: number,\n outMax: number,\n): number {\n const t = (value - inMin) / (inMax - inMin);\n return lerp(outMin, outMax, t);\n}\n","import { lerp, clamp } from \"./lerp.js\";\n\nexport interface RGBA {\n r: number; // 0-255\n g: number; // 0-255\n b: number; // 0-255\n a: number; // 0-1\n}\n\nexport interface HSLA {\n h: number; // 0-360\n s: number; // 0-100\n l: number; // 0-100\n a: number; // 0-1\n}\n\n/**\n * Parse a hex color string to RGBA.\n * Supports: #RGB, #RGBA, #RRGGBB, #RRGGBBAA\n */\nexport function hexToRgba(hex: string): RGBA {\n let h = hex.replace(\"#\", \"\");\n\n if (h.length === 3)\n h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2] + \"ff\";\n else if (h.length === 4)\n h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2] + h[3] + h[3];\n else if (h.length === 6) h = h + \"ff\";\n\n return {\n r: parseInt(h.slice(0, 2), 16),\n g: parseInt(h.slice(2, 4), 16),\n b: parseInt(h.slice(4, 6), 16),\n a: parseInt(h.slice(6, 8), 16) / 255,\n };\n}\n\n/**\n * Convert RGBA to hex string.\n */\nexport function rgbaToHex(color: RGBA): string {\n const r = clamp(Math.round(color.r), 0, 255)\n .toString(16)\n .padStart(2, \"0\");\n const g = clamp(Math.round(color.g), 0, 255)\n .toString(16)\n .padStart(2, \"0\");\n const b = clamp(Math.round(color.b), 0, 255)\n .toString(16)\n .padStart(2, \"0\");\n const a = clamp(Math.round(color.a * 255), 0, 255)\n .toString(16)\n .padStart(2, \"0\");\n return `#${r}${g}${b}${a === \"ff\" ? \"\" : a}`;\n}\n\n/**\n * Interpolate between two RGBA colors.\n */\nexport function lerpRgba(a: RGBA, b: RGBA, t: number): RGBA {\n return {\n r: lerp(a.r, b.r, t),\n g: lerp(a.g, b.g, t),\n b: lerp(a.b, b.b, t),\n a: lerp(a.a, b.a, t),\n };\n}\n\n/**\n * Convert RGBA to HSLA.\n */\nexport function rgbaToHsla(color: RGBA): HSLA {\n const r = color.r / 255;\n const g = color.g / 255;\n const b = color.b / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const d = max - min;\n const l = (max + min) / 2;\n\n let h = 0;\n let s = 0;\n\n if (d !== 0) {\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n else if (max === g) h = ((b - r) / d + 2) / 6;\n else h = ((r - g) / d + 4) / 6;\n }\n\n return { h: h * 360, s: s * 100, l: l * 100, a: color.a };\n}\n\n/**\n * Convert HSLA to RGBA.\n */\nexport function hslaToRgba(color: HSLA): RGBA {\n const h = color.h / 360;\n const s = color.s / 100;\n const l = color.l / 100;\n\n let r: number, g: number, b: number;\n\n if (s === 0) {\n r = g = b = l;\n } else {\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n r = hueToRgb(p, q, h + 1 / 3);\n g = hueToRgb(p, q, h);\n b = hueToRgb(p, q, h - 1 / 3);\n }\n\n return {\n r: Math.round(r * 255),\n g: Math.round(g * 255),\n b: Math.round(b * 255),\n a: color.a,\n };\n}\n\nfunction hueToRgb(p: number, q: number, t: number): number {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n}\n\n/**\n * Interpolate between two HSLA colors (shortest hue path).\n */\nexport function lerpHsla(a: HSLA, b: HSLA, t: number): HSLA {\n // Handle hue wrapping — take the shortest path\n let dh = b.h - a.h;\n if (dh > 180) dh -= 360;\n if (dh < -180) dh += 360;\n\n return {\n h: (((a.h + dh * t) % 360) + 360) % 360,\n s: lerp(a.s, b.s, t),\n l: lerp(a.l, b.l, t),\n a: lerp(a.a, b.a, t),\n };\n}\n","/**\n * Path interpolation utilities for motion paths.\n * Evaluates position and tangent along a path defined by points with bezier handles.\n */\n\nexport interface PathPoint2D {\n x: number;\n y: number;\n in?: { x: number; y: number };\n out?: { x: number; y: number };\n}\n\nexport interface PathPosition {\n x: number;\n y: number;\n /** Tangent angle in degrees */\n angle: number;\n}\n\n/**\n * Compute the length of a single cubic bezier segment using subdivision.\n */\nfunction bezierSegmentLength(\n p0x: number, p0y: number,\n c0x: number, c0y: number,\n c1x: number, c1y: number,\n p1x: number, p1y: number,\n steps = 32,\n): number {\n let length = 0;\n let prevX = p0x;\n let prevY = p0y;\n for (let i = 1; i <= steps; i++) {\n const t = i / steps;\n const mt = 1 - t;\n const x = mt * mt * mt * p0x + 3 * mt * mt * t * c0x + 3 * mt * t * t * c1x + t * t * t * p1x;\n const y = mt * mt * mt * p0y + 3 * mt * mt * t * c0y + 3 * mt * t * t * c1y + t * t * t * p1y;\n const dx = x - prevX;\n const dy = y - prevY;\n length += Math.sqrt(dx * dx + dy * dy);\n prevX = x;\n prevY = y;\n }\n return length;\n}\n\n/**\n * Evaluate a cubic bezier at parameter t, returning position and tangent.\n */\nfunction evalBezier(\n p0x: number, p0y: number,\n c0x: number, c0y: number,\n c1x: number, c1y: number,\n p1x: number, p1y: number,\n t: number,\n): PathPosition {\n const mt = 1 - t;\n const x = mt * mt * mt * p0x + 3 * mt * mt * t * c0x + 3 * mt * t * t * c1x + t * t * t * p1x;\n const y = mt * mt * mt * p0y + 3 * mt * mt * t * c0y + 3 * mt * t * t * c1y + t * t * t * p1y;\n\n // Tangent (first derivative)\n const tx = 3 * mt * mt * (c0x - p0x) + 6 * mt * t * (c1x - c0x) + 3 * t * t * (p1x - c1x);\n const ty = 3 * mt * mt * (c0y - p0y) + 6 * mt * t * (c1y - c0y) + 3 * t * t * (p1y - c1y);\n\n const angle = Math.atan2(ty, tx) * (180 / Math.PI);\n\n return { x, y, angle };\n}\n\n/**\n * Build a lookup table of cumulative segment lengths for a path.\n */\nfunction buildSegmentLengths(points: PathPoint2D[], closed: boolean): number[] {\n const segCount = closed ? points.length : points.length - 1;\n const lengths: number[] = [];\n\n for (let i = 0; i < segCount; i++) {\n const p0 = points[i];\n const p1 = points[(i + 1) % points.length];\n\n const c0x = p0.x + (p0.out?.x ?? 0);\n const c0y = p0.y + (p0.out?.y ?? 0);\n const c1x = p1.x + (p1.in?.x ?? 0);\n const c1y = p1.y + (p1.in?.y ?? 0);\n\n lengths.push(bezierSegmentLength(p0.x, p0.y, c0x, c0y, c1x, c1y, p1.x, p1.y));\n }\n\n return lengths;\n}\n\n/**\n * Evaluate a point along a path at a given progress (0–1).\n * Uses arc-length parameterization for uniform speed.\n */\nexport function evaluatePathAtProgress(\n points: PathPoint2D[],\n progress: number,\n closed = false,\n): PathPosition {\n if (points.length < 2) {\n return { x: points[0]?.x ?? 0, y: points[0]?.y ?? 0, angle: 0 };\n }\n\n // Clamp progress\n const t = Math.max(0, Math.min(1, progress));\n\n const segLengths = buildSegmentLengths(points, closed);\n const totalLength = segLengths.reduce((a, b) => a + b, 0);\n\n if (totalLength === 0) {\n return { x: points[0].x, y: points[0].y, angle: 0 };\n }\n\n const targetLength = t * totalLength;\n\n // Find which segment the target length falls in\n let accumulated = 0;\n for (let i = 0; i < segLengths.length; i++) {\n const segLen = segLengths[i];\n if (accumulated + segLen >= targetLength || i === segLengths.length - 1) {\n // Progress within this segment\n const segProgress = segLen === 0 ? 0 : (targetLength - accumulated) / segLen;\n\n const p0 = points[i];\n const p1 = points[(i + 1) % points.length];\n\n const c0x = p0.x + (p0.out?.x ?? 0);\n const c0y = p0.y + (p0.out?.y ?? 0);\n const c1x = p1.x + (p1.in?.x ?? 0);\n const c1y = p1.y + (p1.in?.y ?? 0);\n\n return evalBezier(p0.x, p0.y, c0x, c0y, c1x, c1y, p1.x, p1.y, segProgress);\n }\n accumulated += segLen;\n }\n\n // Fallback (shouldn't reach here)\n const last = points[points.length - 1];\n return { x: last.x, y: last.y, angle: 0 };\n}\n","import type { Delta, FrameRange } from \"@a-company/atelier-types\";\nimport { lerp, clamp, hexToRgba, lerpRgba, rgbaToHex } from \"@a-company/atelier-math\";\nimport { resolveEasing } from \"./easing-resolver.js\";\nimport { isExpression, evaluateExpression, type ExpressionContext } from \"../expressions/expression-evaluator.js\";\n\n/**\n * Check if a frame is within a delta's range (inclusive).\n */\nexport function isFrameInRange(frame: number, range: FrameRange): boolean {\n return frame >= range[0] && frame <= range[1];\n}\n\n/**\n * Compute the progress (0-1) of a frame within a delta's range.\n */\nexport function computeProgress(frame: number, range: FrameRange): number {\n const [start, end] = range;\n if (start === end) return 1; // instantaneous\n return clamp((frame - start) / (end - start), 0, 1);\n}\n\n/**\n * Resolve a single delta's value at a given frame.\n * Returns undefined if the frame is outside the delta's range.\n * Returns the interpolated value if within range.\n *\n * If `from` or `to` is an expression object `{ expr: \"...\" }`,\n * it is evaluated with the current animation context before interpolation.\n */\nexport function resolveDeltaValue(delta: Delta, frame: number): unknown | undefined {\n if (!isFrameInRange(frame, delta.range)) {\n return undefined;\n }\n\n const progress = computeProgress(frame, delta.range);\n const easingFn = resolveEasing(delta.easing);\n const easedProgress = easingFn(progress);\n\n const exprCtx: ExpressionContext = {\n t: easedProgress,\n progress,\n frame,\n duration: delta.range[1] - delta.range[0],\n };\n\n const from = isExpression(delta.from)\n ? evaluateExpression(delta.from.expr, exprCtx)\n : delta.from;\n\n const to = isExpression(delta.to)\n ? evaluateExpression(delta.to.expr, exprCtx)\n : delta.to;\n\n return interpolateValue(from, to, easedProgress);\n}\n\n/**\n * Interpolate between two values based on eased progress.\n * Handles numbers, strings (pass-through at threshold), and nested objects.\n */\nexport function interpolateValue(from: unknown, to: unknown, t: number): unknown {\n // Number interpolation\n if (typeof from === \"number\" && typeof to === \"number\") {\n return lerp(from, to, t);\n }\n\n // Hex color interpolation\n if (typeof from === \"string\" && typeof to === \"string\") {\n if (from.startsWith(\"#\") && to.startsWith(\"#\")) {\n return rgbaToHex(lerpRgba(hexToRgba(from), hexToRgba(to), t));\n }\n // Non-color strings — snap at end\n return t >= 1 ? to : from;\n }\n\n // Boolean interpolation — snap at midpoint for frame-precise control\n if (typeof from === \"boolean\" && typeof to === \"boolean\") {\n return t >= 0.5 ? to : from;\n }\n\n // For unknown types, snap at end\n return t >= 1 ? to : from;\n}\n\n/**\n * Given multiple deltas for the SAME layer+property, find the active one\n * at a given frame and return its resolved value.\n *\n * If no delta is active at this frame, holds the `to` value of the most\n * recent completed delta (the one whose range ended most recently before\n * this frame). This prevents properties from reverting after animation ends.\n *\n * Assumes no overlaps (validated elsewhere).\n */\nexport function resolvePropertyAtFrame(\n deltas: Delta[],\n frame: number,\n): unknown | undefined {\n // Check for an active delta first\n for (const delta of deltas) {\n if (isFrameInRange(frame, delta.range)) {\n return resolveDeltaValue(delta, frame);\n }\n }\n\n // No active delta — hold the `to` value of the most recently completed delta\n let lastCompleted: Delta | undefined;\n for (const delta of deltas) {\n if (frame > delta.range[1]) {\n if (!lastCompleted || delta.range[1] > lastCompleted.range[1]) {\n lastCompleted = delta;\n }\n }\n }\n\n if (!lastCompleted) return undefined;\n\n // If the held `to` value is an expression, evaluate at t=1\n if (isExpression(lastCompleted.to)) {\n return evaluateExpression(lastCompleted.to.expr, {\n t: 1,\n progress: 1,\n frame,\n duration: lastCompleted.range[1] - lastCompleted.range[0],\n });\n }\n\n return lastCompleted.to;\n}\n","import type { Easing } from \"@a-company/atelier-types\";\nimport { linear, cubicBezier, easeIn, easeOut, easeInOut, step, spring } from \"@a-company/atelier-math\";\n\n/**\n * Converts an Easing type definition into an executable easing function.\n * Returns a function (t: number) => number where t is 0-1.\n */\nexport function resolveEasing(easing: Easing | undefined): (t: number) => number {\n if (!easing) return linear;\n\n // String presets\n if (typeof easing === \"string\") {\n switch (easing) {\n case \"linear\": return linear;\n case \"ease-in\": return easeIn;\n case \"ease-out\": return easeOut;\n case \"ease-in-out\": return easeInOut;\n default: return linear;\n }\n }\n\n // Object easing definitions\n switch (easing.type) {\n case \"linear\":\n return linear;\n case \"cubic-bezier\":\n return cubicBezier(easing.x1, easing.y1, easing.x2, easing.y2);\n case \"spring\":\n return spring({\n mass: easing.mass,\n stiffness: easing.stiffness,\n damping: easing.damping,\n velocity: easing.velocity,\n });\n case \"step\":\n return step(easing.steps, easing.position);\n default:\n return linear;\n }\n}\n","/**\n * Safe recursive descent expression evaluator.\n * No eval(), no Function(), no code generation.\n *\n * Supports:\n * - Numbers: 42, 3.14, -1\n * - Operators: + - * / % **\n * - Parentheses: (expr)\n * - Math functions: sin, cos, tan, abs, min, max, floor, ceil, round, sqrt, pow, clamp, sign, log\n * - Constants: pi, tau, e\n * - Context variables: t, frame, duration, progress\n * - Comparison: <, >, <=, >=, ==, !=\n * - Ternary: condition ? trueExpr : falseExpr\n */\n\n/** Context variables available during expression evaluation */\nexport interface ExpressionContext {\n /** Eased progress 0–1 */\n t: number;\n /** Raw progress 0–1 (before easing) */\n progress: number;\n /** Current frame number */\n frame: number;\n /** Delta duration in frames */\n duration: number;\n}\n\n// ── Tokenizer ───────────────────────────────────────────────\n\ntype TokenType =\n | \"number\"\n | \"ident\"\n | \"op\"\n | \"lparen\"\n | \"rparen\"\n | \"comma\"\n | \"question\"\n | \"colon\"\n | \"compare\"\n | \"eof\";\n\ninterface Token {\n type: TokenType;\n value: string;\n}\n\nfunction tokenize(expr: string): Token[] {\n const tokens: Token[] = [];\n let i = 0;\n\n while (i < expr.length) {\n const ch = expr[i];\n\n // Whitespace\n if (ch === \" \" || ch === \"\\t\" || ch === \"\\n\" || ch === \"\\r\") {\n i++;\n continue;\n }\n\n // Numbers\n if ((ch >= \"0\" && ch <= \"9\") || ch === \".\") {\n let num = \"\";\n while (i < expr.length && ((expr[i] >= \"0\" && expr[i] <= \"9\") || expr[i] === \".\")) {\n num += expr[i++];\n }\n tokens.push({ type: \"number\", value: num });\n continue;\n }\n\n // Identifiers (variables, functions, constants)\n if ((ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\") || ch === \"_\") {\n let id = \"\";\n while (i < expr.length && ((expr[i] >= \"a\" && expr[i] <= \"z\") || (expr[i] >= \"A\" && expr[i] <= \"Z\") || (expr[i] >= \"0\" && expr[i] <= \"9\") || expr[i] === \"_\")) {\n id += expr[i++];\n }\n tokens.push({ type: \"ident\", value: id });\n continue;\n }\n\n // Comparison operators (must check before single-char ops)\n if (ch === \"<\" || ch === \">\" || ch === \"!\" || ch === \"=\") {\n if (i + 1 < expr.length && expr[i + 1] === \"=\") {\n tokens.push({ type: \"compare\", value: ch + \"=\" });\n i += 2;\n continue;\n }\n if (ch === \"<\" || ch === \">\") {\n tokens.push({ type: \"compare\", value: ch });\n i++;\n continue;\n }\n }\n\n // Power operator\n if (ch === \"*\" && i + 1 < expr.length && expr[i + 1] === \"*\") {\n tokens.push({ type: \"op\", value: \"**\" });\n i += 2;\n continue;\n }\n\n // Operators\n if (ch === \"+\" || ch === \"-\" || ch === \"*\" || ch === \"/\" || ch === \"%\") {\n tokens.push({ type: \"op\", value: ch });\n i++;\n continue;\n }\n\n // Grouping and function calls\n if (ch === \"(\") { tokens.push({ type: \"lparen\", value: \"(\" }); i++; continue; }\n if (ch === \")\") { tokens.push({ type: \"rparen\", value: \")\" }); i++; continue; }\n if (ch === \",\") { tokens.push({ type: \"comma\", value: \",\" }); i++; continue; }\n\n // Ternary\n if (ch === \"?\") { tokens.push({ type: \"question\", value: \"?\" }); i++; continue; }\n if (ch === \":\") { tokens.push({ type: \"colon\", value: \":\" }); i++; continue; }\n\n throw new Error(`Expression: unexpected character '${ch}' at position ${i}`);\n }\n\n tokens.push({ type: \"eof\", value: \"\" });\n return tokens;\n}\n\n// ── Parser + Evaluator ──────────────────────────────────────\n\nconst CONSTANTS: Record<string, number> = {\n pi: Math.PI,\n PI: Math.PI,\n tau: Math.PI * 2,\n TAU: Math.PI * 2,\n e: Math.E,\n E: Math.E,\n};\n\nconst FUNCTIONS: Record<string, (...args: number[]) => number> = {\n sin: Math.sin,\n cos: Math.cos,\n tan: Math.tan,\n abs: Math.abs,\n floor: Math.floor,\n ceil: Math.ceil,\n round: Math.round,\n sqrt: Math.sqrt,\n sign: Math.sign,\n log: Math.log,\n min: (...args) => Math.min(...args),\n max: (...args) => Math.max(...args),\n pow: (a, b) => Math.pow(a, b),\n clamp: (v, lo, hi) => Math.min(Math.max(v, lo), hi),\n};\n\nclass Parser {\n private tokens: Token[];\n private pos = 0;\n private ctx: ExpressionContext;\n\n constructor(tokens: Token[], ctx: ExpressionContext) {\n this.tokens = tokens;\n this.ctx = ctx;\n }\n\n private peek(): Token {\n return this.tokens[this.pos];\n }\n\n private consume(expectedType?: TokenType): Token {\n const tok = this.tokens[this.pos++];\n if (expectedType && tok.type !== expectedType) {\n throw new Error(`Expression: expected ${expectedType} but got ${tok.type} '${tok.value}'`);\n }\n return tok;\n }\n\n /** Entry: ternary (lowest precedence) */\n parse(): number {\n const result = this.parseTernary();\n if (this.peek().type !== \"eof\") {\n throw new Error(`Expression: unexpected token '${this.peek().value}'`);\n }\n return result;\n }\n\n /** ternary: comparison ? expr : expr */\n private parseTernary(): number {\n const condition = this.parseComparison();\n if (this.peek().type === \"question\") {\n this.consume(); // ?\n const trueVal = this.parseTernary();\n this.consume(\"colon\"); // :\n const falseVal = this.parseTernary();\n return condition ? trueVal : falseVal;\n }\n return condition;\n }\n\n /** comparison: additive (< | > | <= | >= | == | !=) additive */\n private parseComparison(): number {\n let left = this.parseAdditive();\n while (this.peek().type === \"compare\") {\n const op = this.consume().value;\n const right = this.parseAdditive();\n switch (op) {\n case \"<\": left = left < right ? 1 : 0; break;\n case \">\": left = left > right ? 1 : 0; break;\n case \"<=\": left = left <= right ? 1 : 0; break;\n case \">=\": left = left >= right ? 1 : 0; break;\n case \"==\": left = left === right ? 1 : 0; break;\n case \"!=\": left = left !== right ? 1 : 0; break;\n }\n }\n return left;\n }\n\n /** additive: multiplicative (('+' | '-') multiplicative)* */\n private parseAdditive(): number {\n let left = this.parseMultiplicative();\n while (this.peek().type === \"op\" && (this.peek().value === \"+\" || this.peek().value === \"-\")) {\n const op = this.consume().value;\n const right = this.parseMultiplicative();\n left = op === \"+\" ? left + right : left - right;\n }\n return left;\n }\n\n /** multiplicative: power (('*' | '/' | '%') power)* */\n private parseMultiplicative(): number {\n let left = this.parsePower();\n while (this.peek().type === \"op\" && (this.peek().value === \"*\" || this.peek().value === \"/\" || this.peek().value === \"%\")) {\n const op = this.consume().value;\n const right = this.parsePower();\n if (op === \"*\") left = left * right;\n else if (op === \"/\") left = right !== 0 ? left / right : 0;\n else left = left % right;\n }\n return left;\n }\n\n /** power: unary ('**' unary)* (right-associative) */\n private parsePower(): number {\n const base = this.parseUnary();\n if (this.peek().type === \"op\" && this.peek().value === \"**\") {\n this.consume();\n const exp = this.parsePower(); // right-associative\n return Math.pow(base, exp);\n }\n return base;\n }\n\n /** unary: ('-' | '+') unary | primary */\n private parseUnary(): number {\n if (this.peek().type === \"op\" && (this.peek().value === \"-\" || this.peek().value === \"+\")) {\n const op = this.consume().value;\n const val = this.parseUnary();\n return op === \"-\" ? -val : val;\n }\n return this.parsePrimary();\n }\n\n /** primary: number | ident | function(args) | '(' expr ')' */\n private parsePrimary(): number {\n const tok = this.peek();\n\n // Number literal\n if (tok.type === \"number\") {\n this.consume();\n return parseFloat(tok.value);\n }\n\n // Identifier: constant, context variable, or function\n if (tok.type === \"ident\") {\n this.consume();\n const name = tok.value;\n\n // Function call\n if (this.peek().type === \"lparen\") {\n this.consume(); // (\n const args: number[] = [];\n if (this.peek().type !== \"rparen\") {\n args.push(this.parseTernary());\n while (this.peek().type === \"comma\") {\n this.consume(); // ,\n args.push(this.parseTernary());\n }\n }\n this.consume(\"rparen\"); // )\n\n const fn = FUNCTIONS[name];\n if (!fn) throw new Error(`Expression: unknown function '${name}'`);\n return fn(...args);\n }\n\n // Constant\n if (name in CONSTANTS) return CONSTANTS[name];\n\n // Context variable\n if (name in this.ctx) return (this.ctx as unknown as Record<string, number>)[name];\n\n throw new Error(`Expression: unknown variable '${name}'`);\n }\n\n // Parenthesized expression\n if (tok.type === \"lparen\") {\n this.consume(); // (\n const val = this.parseTernary();\n this.consume(\"rparen\"); // )\n return val;\n }\n\n throw new Error(`Expression: unexpected token '${tok.value}'`);\n }\n}\n\n// ── Public API ──────────────────────────────────────────────\n\n/**\n * Check if a value is an expression object { expr: string }.\n */\nexport function isExpression(value: unknown): value is { expr: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"expr\" in value &&\n typeof (value as Record<string, unknown>).expr === \"string\"\n );\n}\n\n/**\n * Evaluate an expression string with the given context.\n * Returns a number. Throws on syntax errors or unknown identifiers.\n */\nexport function evaluateExpression(expr: string, ctx: ExpressionContext): number {\n const tokens = tokenize(expr);\n const parser = new Parser(tokens, ctx);\n return parser.parse();\n}\n","import type { AtelierDocument, Layer, Delta, AnimatableProperty, VideoVisual } from \"@a-company/atelier-types\";\nimport { resolvePropertyAtFrame } from \"./delta-resolver.js\";\n\n/** A resolved layer at a specific frame — all animated properties computed */\nexport interface ResolvedLayer {\n id: string;\n /** Original layer definition */\n layer: Layer;\n /** Computed property overrides from active deltas */\n computedProperties: Partial<Record<AnimatableProperty, unknown>>;\n /** Seconds into source video to seek to — only present for video visual layers */\n videoSourceTime?: number;\n}\n\n/** The resolved state of an entire document at a specific frame */\nexport interface ResolvedFrame {\n /** Frame number that was resolved */\n frame: number;\n /** State name that was resolved */\n stateName: string;\n /** All layers with their computed properties */\n layers: ResolvedLayer[];\n}\n\n/**\n * Resolve all layers at a given frame within a named state.\n * This is the main entry point for frame resolution.\n * @param overrideDeltas - Optional pre-merged deltas (used for hierarchical state resolution)\n */\nexport function resolveFrame(\n doc: AtelierDocument,\n stateName: string,\n frame: number,\n overrideDeltas?: Delta[],\n): ResolvedFrame {\n const state = doc.states[stateName];\n if (!state) {\n throw new Error(`State \"${stateName}\" not found in document \"${doc.name}\"`);\n }\n\n // Group deltas by layer+property\n const deltasByLayerProperty = groupDeltas(overrideDeltas ?? state.deltas);\n\n // Pre-compute the nearest ancestor video-clip startFrame for every layer.\n // v1.0 multi-clip: captions parented to a clip (parentId = clip-layer-id)\n // author their deltas in clip-local frames (0..clipDuration). The renderer\n // shifts the evaluation frame by the parent clip's startFrame so the deltas\n // fire when the clip is actually playing on the composition timeline. This\n // is what makes \"move a clip and its captions go with it\" work.\n const ancestorClipStartFrame = computeAncestorClipStartFrames(doc);\n\n // Resolve each layer\n const resolvedLayers: ResolvedLayer[] = doc.layers.map((layer) => {\n const computedProperties: Partial<Record<AnimatableProperty, unknown>> = {};\n\n // Find all animated properties for this layer\n const layerDeltas = deltasByLayerProperty.get(layer.id);\n if (layerDeltas) {\n // Clip-local time = composition frame - nearest ancestor video startFrame.\n // For layers with no video ancestor, the offset is 0 (no shift).\n const offset = ancestorClipStartFrame.get(layer.id) ?? 0;\n const localFrame = frame - offset;\n for (const [property, deltas] of layerDeltas) {\n const value = resolvePropertyAtFrame(deltas, localFrame);\n if (value !== undefined) {\n computedProperties[property as AnimatableProperty] = value;\n }\n }\n }\n\n const resolvedLayer: ResolvedLayer = { id: layer.id, layer, computedProperties };\n\n if (layer.visual.type === \"video\") {\n const video = layer.visual;\n const fps = doc.canvas.fps;\n const startFrame = video.startFrame ?? 0;\n const sourceOffset = video.sourceOffset ?? 0;\n const playbackRate = video.playbackRate ?? 1.0;\n const relativeFrame = Math.max(0, frame - startFrame);\n const sourceTime = (relativeFrame / fps) * playbackRate + sourceOffset;\n resolvedLayer.videoSourceTime =\n video.sourceEnd !== undefined ? Math.min(sourceTime, video.sourceEnd) : sourceTime;\n }\n\n return resolvedLayer;\n });\n\n return { frame, stateName, layers: resolvedLayers };\n}\n\n/**\n * For each layer in the document, walk the parentId chain looking for the\n * nearest ancestor whose visual is a VideoVisual; return that ancestor's\n * `startFrame` (or 0 if no video ancestor exists). The result is a\n * layer-id → offset map used to shift delta evaluation into clip-local time.\n *\n * Note: this resolves only on a video clip ancestor, not on Group or other\n * layer types. A Group used as a \"track\" doesn't shift child time — only the\n * clip itself does. This keeps non-clip parenting (groups for positioning,\n * masks, etc.) decoupled from the timeline-shift behavior.\n *\n * Cycle-safe via a visited set; a malformed doc with parentId cycles falls\n * back to offset 0 for affected layers rather than looping.\n */\nfunction computeAncestorClipStartFrames(doc: AtelierDocument): Map<string, number> {\n const byId = new Map<string, Layer>();\n for (const l of doc.layers) byId.set(l.id, l);\n\n const result = new Map<string, number>();\n for (const layer of doc.layers) {\n let cursor: Layer | undefined = byId.get(layer.parentId ?? \"\");\n const visited = new Set<string>();\n while (cursor) {\n if (visited.has(cursor.id)) break;\n visited.add(cursor.id);\n if (cursor.visual.type === \"video\") {\n const v = cursor.visual as VideoVisual;\n result.set(layer.id, v.startFrame ?? 0);\n break;\n }\n cursor = byId.get(cursor.parentId ?? \"\");\n }\n }\n return result;\n}\n\n/**\n * Group deltas by layer ID, then by property name.\n */\nfunction groupDeltas(\n deltas: Delta[],\n): Map<string, Map<string, Delta[]>> {\n const map = new Map<string, Map<string, Delta[]>>();\n\n for (const delta of deltas) {\n let layerMap = map.get(delta.layer);\n if (!layerMap) {\n layerMap = new Map();\n map.set(delta.layer, layerMap);\n }\n\n let propDeltas = layerMap.get(delta.property);\n if (!propDeltas) {\n propDeltas = [];\n layerMap.set(delta.property, propDeltas);\n }\n\n propDeltas.push(delta);\n }\n\n return map;\n}\n","import type { Delta, FrameRange } from \"@a-company/atelier-types\";\n\nexport interface OverlapError {\n layerId: string;\n property: string;\n existingRange: FrameRange;\n newRange: FrameRange;\n message: string;\n}\n\n/**\n * Check if two frame ranges overlap.\n * Boundary-touching ranges (e.g., [0-50] and [50-90]) are allowed —\n * only ranges that share more than a single boundary frame are overlaps.\n */\nexport function rangesOverlap(a: FrameRange, b: FrameRange): boolean {\n return a[0] < b[1] && b[0] < a[1];\n}\n\n/**\n * Validate that a new delta doesn't overlap with existing deltas\n * on the same layer+property.\n */\nexport function validateNoOverlap(\n existing: Delta[],\n newDelta: Delta,\n): OverlapError | null {\n for (const delta of existing) {\n if (\n delta.layer === newDelta.layer &&\n delta.property === newDelta.property &&\n rangesOverlap(delta.range, newDelta.range)\n ) {\n return {\n layerId: newDelta.layer,\n property: newDelta.property,\n existingRange: delta.range,\n newRange: newDelta.range,\n message: `Overlapping delta on layer \"${newDelta.layer}\" property \"${newDelta.property}\": ` +\n `existing [${delta.range[0]}-${delta.range[1]}] overlaps with new [${newDelta.range[0]}-${newDelta.range[1]}]`,\n };\n }\n }\n return null;\n}\n\n/**\n * Validate all deltas in a state have no overlaps.\n * Returns all overlap errors found.\n */\nexport function validateAllDeltas(deltas: Delta[]): OverlapError[] {\n const errors: OverlapError[] = [];\n\n for (let i = 0; i < deltas.length; i++) {\n for (let j = i + 1; j < deltas.length; j++) {\n const a = deltas[i];\n const b = deltas[j];\n\n if (\n a.layer === b.layer &&\n a.property === b.property &&\n rangesOverlap(a.range, b.range)\n ) {\n errors.push({\n layerId: a.layer,\n property: a.property,\n existingRange: a.range,\n newRange: b.range,\n message: `Overlapping deltas on layer \"${a.layer}\" property \"${a.property}\": ` +\n `[${a.range[0]}-${a.range[1]}] overlaps with [${b.range[0]}-${b.range[1]}]`,\n });\n }\n }\n }\n\n return errors;\n}\n","import type {\n AtelierDocument, Canvas, Layer, State, Delta, Preset,\n Variable, Asset,\n} from \"@a-company/atelier-types\";\nimport { validateNoOverlap } from \"../validation/overlap-validator.js\";\n\n/**\n * Fluent builder for constructing AtelierDocument objects.\n * Validates constraints (like no-overlap) as you build.\n */\nexport class DocumentBuilder {\n private doc: AtelierDocument;\n\n constructor(name: string, canvas: Canvas) {\n this.doc = {\n version: \"1.0\",\n name,\n canvas,\n layers: [],\n states: {},\n };\n }\n\n /** Set document description */\n description(desc: string): this {\n this.doc.description = desc;\n return this;\n }\n\n /** Add tags to the document */\n tags(...tags: string[]): this {\n this.doc.tags = [...(this.doc.tags ?? []), ...tags];\n return this;\n }\n\n /** Add a variable definition */\n variable(id: string, variable: Variable): this {\n if (!this.doc.variables) this.doc.variables = {};\n this.doc.variables[id] = variable;\n return this;\n }\n\n /** Add an asset reference */\n asset(id: string, asset: Asset): this {\n if (!this.doc.assets) this.doc.assets = {};\n this.doc.assets[id] = asset;\n return this;\n }\n\n /** Add a preset */\n preset(id: string, preset: Preset): this {\n if (!this.doc.presets) this.doc.presets = {};\n this.doc.presets[id] = preset;\n return this;\n }\n\n /** Add a layer */\n addLayer(layer: Layer): this {\n // Check for duplicate IDs\n if (this.doc.layers.some(l => l.id === layer.id)) {\n throw new Error(`Layer with id \"${layer.id}\" already exists`);\n }\n this.doc.layers.push(layer);\n return this;\n }\n\n /** Add a state */\n addState(name: string, state: Omit<State, \"deltas\"> & { deltas?: Delta[] }): this {\n if (this.doc.states[name]) {\n throw new Error(`State \"${name}\" already exists`);\n }\n this.doc.states[name] = { ...state, deltas: state.deltas ?? [] };\n return this;\n }\n\n /** Add a delta to an existing state, with overlap validation */\n addDelta(stateName: string, delta: Delta): this {\n const state = this.doc.states[stateName];\n if (!state) {\n throw new Error(`State \"${stateName}\" not found`);\n }\n\n // Verify the layer exists\n if (!this.doc.layers.some(l => l.id === delta.layer)) {\n throw new Error(`Layer \"${delta.layer}\" not found — add the layer before adding deltas`);\n }\n\n // Check for overlaps\n const overlap = validateNoOverlap(state.deltas, delta);\n if (overlap) {\n throw new Error(overlap.message);\n }\n\n state.deltas.push(delta);\n return this;\n }\n\n /** Build and return the final document */\n build(): AtelierDocument {\n return JSON.parse(JSON.stringify(this.doc)) as AtelierDocument;\n }\n}\n\n/**\n * Create a new DocumentBuilder.\n * Convenience function for starting a builder chain.\n */\nexport function createDocument(name: string, canvas: Canvas): DocumentBuilder {\n return new DocumentBuilder(name, canvas);\n}\n","import type { UnitValue } from \"@a-company/atelier-types\";\n\n/**\n * Check if a UnitValue is a percentage string.\n */\nexport function isPercentage(value: UnitValue): value is `${number}%` {\n return typeof value === \"string\" && value.endsWith(\"%\");\n}\n\n/**\n * Parse a percentage string to its numeric value (0-100).\n */\nexport function parsePercentage(value: `${number}%`): number {\n return parseFloat(value);\n}\n\n/**\n * Resolve a UnitValue to pixels given a reference dimension.\n * Pixel values pass through unchanged.\n * Percentage values are computed relative to the reference.\n */\nexport function resolveUnit(value: UnitValue, reference: number): number {\n if (isPercentage(value)) {\n return (parsePercentage(value) / 100) * reference;\n }\n return value;\n}\n","import type { Preset, Delta, FrameRange } from \"@a-company/atelier-types\";\n\n/**\n * Expand a preset into concrete deltas for a specific layer and start frame.\n *\n * @param preset - The preset to expand\n * @param layerId - Target layer ID\n * @param startFrame - Frame to start the preset from\n * @param duration - Total duration to map preset offsets into\n */\nexport function expandPreset(\n preset: Preset,\n layerId: string,\n startFrame: number,\n duration: number,\n): Delta[] {\n return preset.deltas.map((pd, index) => {\n let range: FrameRange;\n if (pd.offset) {\n range = [startFrame + pd.offset[0], startFrame + pd.offset[1]];\n } else {\n range = [startFrame, startFrame + duration];\n }\n\n return {\n id: `preset-${layerId}-${index}`,\n layer: layerId,\n property: pd.property,\n range,\n from: pd.from,\n to: pd.to,\n easing: pd.easing,\n };\n });\n}\n","import type { AtelierDocument, Easing, State, Delta } from \"@a-company/atelier-types\";\nimport { resolveFrame, type ResolvedFrame } from \"../resolver/frame-resolver.js\";\nimport { resolveEasing } from \"../resolver/easing-resolver.js\";\n\nexport interface StateTransition {\n from: string;\n to: string;\n at: number; // frame at which transition occurs\n}\n\nexport interface PlaybackState {\n stateName: string;\n frame: number;\n resolved: ResolvedFrame;\n isComplete: boolean;\n}\n\nexport interface ActiveTransition {\n fromState: string;\n toState: string;\n duration: number;\n easingFn: (t: number) => number;\n transitionFrame: number; // how many frames into the transition\n}\n\nexport class StateMachine {\n private currentState: string;\n private currentFrame = 0;\n private transitions: StateTransition[] = [];\n private activeTransition: ActiveTransition | null = null;\n\n constructor(\n private doc: AtelierDocument,\n initialState?: string,\n ) {\n // Default to first state\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) throw new Error(\"Document has no states\");\n this.currentState = initialState ?? stateNames[0];\n if (!doc.states[this.currentState]) {\n throw new Error(`State \"${this.currentState}\" not found`);\n }\n }\n\n /** Get current state name */\n get state(): string {\n return this.currentState;\n }\n\n /** Get current frame */\n get frame(): number {\n return this.currentFrame;\n }\n\n /** Get all state names */\n get stateNames(): string[] {\n return Object.keys(this.doc.states);\n }\n\n /** Get current state duration */\n get duration(): number {\n return this.doc.states[this.currentState].duration;\n }\n\n /** Check if current state playback is complete */\n get isComplete(): boolean {\n return this.currentFrame >= this.duration - 1;\n }\n\n /** Check if currently in a transition blend */\n isTransitioning(): boolean {\n return this.activeTransition !== null;\n }\n\n /** Get transition progress (0–1) with easing applied, or null if not transitioning */\n getTransitionProgress(): number | null {\n if (!this.activeTransition) return null;\n const { transitionFrame, duration, easingFn } = this.activeTransition;\n const rawProgress = Math.min(transitionFrame / duration, 1);\n return easingFn(rawProgress);\n }\n\n // ── Hierarchical State Support ────────────────────────────\n\n /**\n * Resolve the ancestor chain for a state (root → … → parent → self).\n * Throws on circular parent references.\n */\n resolveAncestorChain(stateName: string): string[] {\n const chain: string[] = [];\n const visited = new Set<string>();\n let current: string | undefined = stateName;\n\n while (current) {\n if (visited.has(current)) {\n throw new Error(`Circular parent reference detected: \"${current}\" already in chain [${chain.join(\" → \")}]`);\n }\n visited.add(current);\n chain.unshift(current); // prepend so root is first\n const stateObj: State | undefined = this.doc.states[current];\n if (!stateObj) {\n throw new Error(`Parent state \"${current}\" not found`);\n }\n current = stateObj.parent;\n }\n\n return chain;\n }\n\n /**\n * Collect merged deltas from ancestor chain.\n * Child overrides parent deltas for the same layer+property combination.\n * Deltas for different layer+property pairs are accumulated from all ancestors.\n */\n collectDeltas(stateName: string): Delta[] {\n const chain = this.resolveAncestorChain(stateName);\n // Walk root → child. Later entries override earlier for same layer+property.\n const deltaMap = new Map<string, Delta[]>();\n\n for (const ancestorName of chain) {\n const state = this.doc.states[ancestorName];\n // Group this state's deltas by layer+property\n const stateGroups = new Map<string, Delta[]>();\n for (const delta of state.deltas) {\n const key = `${delta.layer}:${delta.property}`;\n if (!stateGroups.has(key)) stateGroups.set(key, []);\n stateGroups.get(key)!.push(delta);\n }\n // Child replaces parent for same key\n for (const [key, deltas] of stateGroups) {\n deltaMap.set(key, deltas);\n }\n }\n\n // Flatten all deltas\n const result: Delta[] = [];\n for (const deltas of deltaMap.values()) {\n result.push(...deltas);\n }\n return result;\n }\n\n // ── Playback ──────────────────────────────────────────────\n\n /** Advance to next frame, returns resolved frame */\n tick(): PlaybackState {\n // Handle active transition\n if (this.activeTransition) {\n this.activeTransition.transitionFrame++;\n if (this.activeTransition.transitionFrame >= this.activeTransition.duration) {\n // Transition complete\n this.activeTransition = null;\n }\n }\n\n const resolved = this.resolveCurrentFrame();\n const result: PlaybackState = {\n stateName: this.currentState,\n frame: this.currentFrame,\n resolved,\n isComplete: this.isComplete,\n };\n if (this.currentFrame < this.duration - 1) {\n this.currentFrame++;\n }\n return result;\n }\n\n /** Resolve the current frame, blending if in transition */\n private resolveCurrentFrame(): ResolvedFrame {\n if (this.activeTransition) {\n const progress = this.getTransitionProgress()!;\n const fromResolved = resolveFrame(\n this.doc, this.activeTransition.fromState, this.currentFrame,\n this.collectDeltas(this.activeTransition.fromState),\n );\n const toResolved = resolveFrame(\n this.doc, this.activeTransition.toState, this.currentFrame,\n this.collectDeltas(this.activeTransition.toState),\n );\n return blendResolvedFrames(fromResolved, toResolved, progress);\n }\n\n // Check if current state has a parent — use merged deltas\n const state = this.doc.states[this.currentState];\n if (state.parent) {\n const mergedDeltas = this.collectDeltas(this.currentState);\n return resolveFrame(this.doc, this.currentState, this.currentFrame, mergedDeltas);\n }\n\n return resolveFrame(this.doc, this.currentState, this.currentFrame);\n }\n\n /** Transition to a different state (instant or blended) */\n transition(stateName: string, startFrame = 0): void {\n if (!this.doc.states[stateName]) {\n throw new Error(`State \"${stateName}\" not found`);\n }\n\n const fromState = this.currentState;\n const currentStateObj = this.doc.states[fromState];\n const transConfig = currentStateObj.transitions?.[stateName];\n\n this.transitions.push({\n from: fromState,\n to: stateName,\n at: this.currentFrame,\n });\n\n if (transConfig && transConfig.duration > 0) {\n // Start a smooth transition\n this.activeTransition = {\n fromState,\n toState: stateName,\n duration: transConfig.duration,\n easingFn: resolveEasing(transConfig.easing),\n transitionFrame: 0,\n };\n }\n\n this.currentState = stateName;\n this.currentFrame = startFrame;\n }\n\n /**\n * Start a smooth transition to target state with explicit duration/easing.\n * This ignores any transitions config on the state.\n */\n transitionTo(targetState: string, duration: number, easing?: Easing): void {\n if (!this.doc.states[targetState]) {\n throw new Error(`State \"${targetState}\" not found`);\n }\n\n const fromState = this.currentState;\n this.transitions.push({\n from: fromState,\n to: targetState,\n at: this.currentFrame,\n });\n\n this.activeTransition = {\n fromState,\n toState: targetState,\n duration,\n easingFn: resolveEasing(easing),\n transitionFrame: 0,\n };\n\n this.currentState = targetState;\n this.currentFrame = 0;\n }\n\n /** Seek to a specific frame in current state */\n seek(frame: number): void {\n this.currentFrame = Math.max(0, Math.min(frame, this.duration - 1));\n }\n\n /** Reset to initial state */\n reset(stateName?: string): void {\n if (stateName) {\n if (!this.doc.states[stateName]) throw new Error(`State \"${stateName}\" not found`);\n this.currentState = stateName;\n }\n this.currentFrame = 0;\n this.activeTransition = null;\n }\n\n /** Get transition history */\n get history(): ReadonlyArray<StateTransition> {\n return this.transitions;\n }\n\n /** Resolve a specific frame without advancing */\n resolveAt(stateName: string, frame: number): ResolvedFrame {\n if (!this.doc.states[stateName]) throw new Error(`State \"${stateName}\" not found`);\n const state = this.doc.states[stateName];\n if (state.parent) {\n return resolveFrame(this.doc, stateName, frame, this.collectDeltas(stateName));\n }\n return resolveFrame(this.doc, stateName, frame);\n }\n\n /** Play through entire current state, calling callback on each frame */\n playThrough(onFrame: (state: PlaybackState) => void): void {\n this.currentFrame = 0;\n while (!this.isComplete) {\n onFrame(this.tick());\n }\n onFrame(this.tick()); // last frame\n }\n}\n\n// ── Frame Blending ────────────────────────────────────────────\n\nimport type { ResolvedLayer } from \"../resolver/frame-resolver.js\";\nimport type { AnimatableProperty } from \"@a-company/atelier-types\";\nimport { interpolateValue } from \"../resolver/delta-resolver.js\";\n\n/**\n * Blend two resolved frames together for smooth state transitions.\n * Numeric properties are lerped, colors are color-lerped, discrete values snap at t >= 0.5.\n */\nexport function blendResolvedFrames(\n frameA: ResolvedFrame,\n frameB: ResolvedFrame,\n t: number,\n): ResolvedFrame {\n // Build layer maps\n const mapA = new Map<string, ResolvedLayer>();\n const mapB = new Map<string, ResolvedLayer>();\n for (const l of frameA.layers) mapA.set(l.id, l);\n for (const l of frameB.layers) mapB.set(l.id, l);\n\n // Get all unique layer IDs\n const allIds = new Set([...mapA.keys(), ...mapB.keys()]);\n const blendedLayers: ResolvedLayer[] = [];\n\n for (const id of allIds) {\n const layerA = mapA.get(id);\n const layerB = mapB.get(id);\n\n if (layerA && layerB) {\n // Both exist — blend computed properties\n blendedLayers.push(blendLayers(layerA, layerB, t));\n } else if (layerA && !layerB) {\n // Only in A — fade out (set opacity toward 0)\n blendedLayers.push(fadeLayer(layerA, 1 - t));\n } else if (!layerA && layerB) {\n // Only in B — fade in (set opacity from 0)\n blendedLayers.push(fadeLayer(layerB, t));\n }\n }\n\n return {\n frame: frameB.frame,\n stateName: frameB.stateName,\n layers: blendedLayers,\n };\n}\n\nfunction blendLayers(a: ResolvedLayer, b: ResolvedLayer, t: number): ResolvedLayer {\n const allProps = new Set([\n ...Object.keys(a.computedProperties),\n ...Object.keys(b.computedProperties),\n ]);\n\n const blended: Partial<Record<AnimatableProperty, unknown>> = {};\n\n for (const prop of allProps) {\n const valA = a.computedProperties[prop as AnimatableProperty];\n const valB = b.computedProperties[prop as AnimatableProperty];\n\n if (valA !== undefined && valB !== undefined) {\n blended[prop as AnimatableProperty] = interpolateValue(valA, valB, t);\n } else if (valA !== undefined) {\n blended[prop as AnimatableProperty] = valA;\n } else {\n blended[prop as AnimatableProperty] = valB;\n }\n }\n\n return {\n id: a.id,\n layer: a.layer,\n computedProperties: blended,\n };\n}\n\nfunction fadeLayer(layer: ResolvedLayer, opacity: number): ResolvedLayer {\n const cp = { ...layer.computedProperties };\n const existingOpacity = (cp.opacity as number) ?? 1;\n cp.opacity = existingOpacity * opacity;\n return {\n id: layer.id,\n layer: layer.layer,\n computedProperties: cp,\n };\n}\n","import type { AtelierDocument } from \"@a-company/atelier-types\";\n\nexport interface TemplateBindings {\n [variableName: string]: unknown;\n}\n\nexport interface TemplateError {\n variable: string;\n message: string;\n}\n\nexport type TemplateResult =\n | {\n success: true;\n document: AtelierDocument;\n }\n | {\n success: false;\n errors: TemplateError[];\n };\n\n/**\n * Instantiate a template document by substituting variable values.\n * Walks the document tree, replacing {{variableName}} patterns with bound values.\n */\nexport function instantiateTemplate(\n template: AtelierDocument,\n bindings: TemplateBindings,\n): TemplateResult {\n // 1. Validate all required variables have bindings\n const errors: TemplateError[] = [];\n const variables = template.variables ?? {};\n\n for (const [name, variable] of Object.entries(variables)) {\n if (bindings[name] === undefined && variable.default === undefined) {\n errors.push({ variable: name, message: `Required variable \"${name}\" not provided` });\n }\n }\n\n // Check for unknown bindings\n for (const name of Object.keys(bindings)) {\n if (!variables[name]) {\n errors.push({ variable: name, message: `Unknown variable \"${name}\"` });\n }\n }\n\n if (errors.length > 0) return { success: false, errors };\n\n // 2. Merge bindings with defaults\n const resolved: Record<string, unknown> = {};\n for (const [name, variable] of Object.entries(variables)) {\n resolved[name] = bindings[name] ?? variable.default;\n }\n\n // 3. Deep clone and substitute\n const doc = JSON.parse(JSON.stringify(template)) as AtelierDocument;\n substituteInObject(doc as unknown as Record<string, unknown>, resolved);\n\n // 4. Remove variables section (no longer a template)\n delete doc.variables;\n\n return { success: true, document: doc };\n}\n\n/**\n * Recursively substitute {{variableName}} patterns in string values.\n */\nfunction substituteInObject(obj: Record<string, unknown>, bindings: Record<string, unknown>): void {\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (typeof value === \"string\") {\n obj[key] = substituteString(value, bindings);\n } else if (Array.isArray(value)) {\n substituteInArray(value, bindings);\n } else if (value !== null && typeof value === \"object\") {\n substituteInObject(value as Record<string, unknown>, bindings);\n }\n }\n}\n\nfunction substituteInArray(arr: unknown[], bindings: Record<string, unknown>): void {\n for (let i = 0; i < arr.length; i++) {\n const value = arr[i];\n if (typeof value === \"string\") {\n arr[i] = substituteString(value, bindings);\n } else if (Array.isArray(value)) {\n substituteInArray(value, bindings);\n } else if (value !== null && typeof value === \"object\") {\n substituteInObject(value as Record<string, unknown>, bindings);\n }\n }\n}\n\n/**\n * Replace {{variableName}} in a string with the bound value.\n * If the entire string is a single {{var}}, return the raw value (preserving type).\n * Otherwise, interpolate into the string.\n */\nfunction substituteString(str: string, bindings: Record<string, unknown>): unknown {\n // Exact match: entire string is {{varName}} -> return raw value\n const exactMatch = str.match(/^\\{\\{(\\w+)\\}\\}$/);\n if (exactMatch) {\n const name = exactMatch[1];\n return name in bindings ? bindings[name] : str;\n }\n\n // Partial match: replace all {{varName}} occurrences with string values\n return str.replace(/\\{\\{(\\w+)\\}\\}/g, (_, name: string) => {\n return name in bindings ? String(bindings[name]) : `{{${name}}}`;\n });\n}\n\n/**\n * List all variables used in a document (scan for {{variableName}} patterns).\n */\nexport function findTemplateVariables(doc: AtelierDocument): string[] {\n const vars = new Set<string>();\n scanForVariables(doc, vars);\n return Array.from(vars);\n}\n\nfunction scanForVariables(value: unknown, vars: Set<string>): void {\n if (typeof value === \"string\") {\n const matches = value.matchAll(/\\{\\{(\\w+)\\}\\}/g);\n for (const match of matches) {\n vars.add(match[1]);\n }\n } else if (Array.isArray(value)) {\n for (const item of value) scanForVariables(item, vars);\n } else if (value !== null && typeof value === \"object\") {\n for (const v of Object.values(value as Record<string, unknown>)) {\n scanForVariables(v, vars);\n }\n }\n}\n","import type { AudioVisual } from \"@a-company/atelier-types\";\n\n/**\n * Audio-layer playback utilities.\n *\n * v1.0: audio is no longer a per-state field. These utilities now take an\n * `AudioVisual` layer (see `@a-company/atelier-types/layer.ts`) and a\n * composition frame; they answer \"is this layer playing right now, at what\n * source-time, at what volume?\".\n *\n * Pure functions — no I/O, no state. Reusable by the canvas renderer's\n * audio scheduler and by any export pipeline (e.g. an ffmpeg mux step).\n */\n\n/** Audio playback state at a given composition frame */\nexport interface AudioPlaybackState {\n /** Whether audio should be playing at this frame */\n shouldPlay: boolean;\n /** Current position in the audio source (seconds) */\n currentTime: number;\n /** Effective volume (0–1), accounting for fadeIn/fadeOut envelopes */\n volume: number;\n}\n\n/** Convert a frame number to time in seconds. */\nexport function frameToTime(frame: number, fps: number): number {\n return frame / fps;\n}\n\n/** Convert time in seconds to a frame number (floored). */\nexport function timeToFrame(time: number, fps: number): number {\n return Math.floor(time * fps);\n}\n\n/**\n * Compute the playback state of an audio layer at a given composition frame.\n *\n * @param layer The AudioVisual to evaluate.\n * @param frame Current composition frame.\n * @param fps Canvas fps.\n * @param totalFrames Total composition duration in frames (used for fade-out\n * anchor when the layer plays to the end of the comp).\n * @returns Whether the layer is audible at this frame, where the\n * source playhead is, and the effective volume after\n * fade envelopes.\n */\nexport function computeAudioState(\n layer: AudioVisual,\n frame: number,\n fps: number,\n totalFrames: number,\n): AudioPlaybackState {\n const startFrame = layer.startFrame ?? 0;\n const sourceOffset = layer.sourceOffset ?? 0;\n const baseVolume = layer.muted ? 0 : (layer.volume ?? 1);\n const playbackRate = layer.playbackRate ?? 1;\n\n // Before the layer starts on the composition timeline.\n if (frame < startFrame) {\n return { shouldPlay: false, currentTime: 0, volume: baseVolume };\n }\n\n // Layer's effective end on the composition timeline. Derived from sourceEnd\n // (clip-out point) if set, otherwise plays to totalFrames.\n let endFrame = totalFrames;\n if (layer.sourceEnd !== undefined) {\n const segmentSec = (layer.sourceEnd - sourceOffset) / playbackRate;\n endFrame = Math.min(totalFrames, startFrame + timeToFrame(segmentSec, fps));\n }\n\n if (frame >= endFrame) {\n return { shouldPlay: false, currentTime: 0, volume: baseVolume };\n }\n\n const elapsedFrames = frame - startFrame;\n const elapsedTime = frameToTime(elapsedFrames, fps);\n const currentTime = sourceOffset + elapsedTime * playbackRate;\n\n // Apply fade envelopes (in/out are seconds at the LAYER edges, not source edges).\n let volume = baseVolume;\n if (layer.fadeIn && layer.fadeIn > 0) {\n const inFrames = timeToFrame(layer.fadeIn, fps);\n if (elapsedFrames < inFrames && inFrames > 0) {\n volume *= elapsedFrames / inFrames;\n }\n }\n if (layer.fadeOut && layer.fadeOut > 0) {\n const outFrames = timeToFrame(layer.fadeOut, fps);\n const framesUntilEnd = endFrame - frame;\n if (framesUntilEnd < outFrames && outFrames > 0) {\n volume *= framesUntilEnd / outFrames;\n }\n }\n\n return { shouldPlay: true, currentTime, volume };\n}\n\n/**\n * Compute cue points for an audio layer — frames where audio events occur\n * (start, end). Useful for scheduling DOM/audio-context play/stop calls.\n *\n * v1.0: with `loop` removed from the schema (AudioVisual doesn't support\n * looping yet — add when a real use case lands), there are at most two\n * cues per layer: start and end.\n */\nexport function computeAudioCues(\n layer: AudioVisual,\n fps: number,\n totalFrames: number,\n): Array<{ frame: number; event: \"start\" | \"end\" }> {\n const startFrame = layer.startFrame ?? 0;\n const sourceOffset = layer.sourceOffset ?? 0;\n const playbackRate = layer.playbackRate ?? 1;\n const cues: Array<{ frame: number; event: \"start\" | \"end\" }> = [];\n\n if (startFrame >= totalFrames) return cues;\n cues.push({ frame: startFrame, event: \"start\" });\n\n let endFrame = totalFrames;\n if (layer.sourceEnd !== undefined) {\n const segmentSec = (layer.sourceEnd - sourceOffset) / playbackRate;\n endFrame = Math.min(totalFrames, startFrame + timeToFrame(segmentSec, fps));\n }\n if (endFrame > startFrame && endFrame <= totalFrames) {\n cues.push({ frame: endFrame - 1, event: \"end\" });\n }\n\n return cues;\n}\n","// @a-company/atelier-mcp — Preset management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Preset, PresetDelta } from \"@a-company/atelier-types\";\nimport { AnimatablePropertySchema, EasingSchema } from \"@a-company/atelier-schema\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\n// Canonical source: @a-company/atelier-schema — single source of truth for AnimatableProperty\nconst AnimatablePropertyEnum = AnimatablePropertySchema;\nconst EasingInputSchema = EasingSchema;\n\nconst PresetDeltaSchema = z.object({\n property: AnimatablePropertyEnum.describe(\"Animatable property\"),\n offset: z.tuple([z.number().int().min(0), z.number().int().min(0)]).optional().describe(\"Relative frame offset [start, end]\"),\n from: z.unknown().describe(\"Starting value\"),\n to: z.unknown().describe(\"Ending value\"),\n easing: EasingInputSchema.optional().describe(\"Easing function\"),\n});\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_define_preset ───────────────────────────────────\n server.tool(\n \"atelier_define_preset\",\n \"Define a reusable animation preset on a document\",\n {\n id: z.string().describe(\"Document ID\"),\n presetName: z.string().describe(\"Preset name\"),\n description: z.string().optional().describe(\"Preset description\"),\n tags: z.array(z.string()).optional().describe(\"Tags\"),\n deltas: z.array(PresetDeltaSchema).min(1).describe(\"Array of preset delta definitions\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, presetName, description, tags, deltas }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.presets) doc.presets = {};\n\n const preset: Preset = {\n deltas: deltas as unknown as PresetDelta[],\n ...(description ? { description } : {}),\n ...(tags ? { tags } : {}),\n };\n\n doc.presets[presetName] = preset;\n\n return ok({ presetName, deltaCount: deltas.length });\n },\n );\n\n // ── atelier_list_presets ────────────────────────────────────\n server.tool(\n \"atelier_list_presets\",\n \"List all presets defined on a document\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.presets || Object.keys(doc.presets).length === 0) {\n return ok({ presets: [], count: 0 });\n }\n\n const presets = Object.entries(doc.presets).map(([name, preset]) => ({\n name,\n description: preset.description,\n tags: preset.tags,\n deltaCount: preset.deltas.length,\n properties: preset.deltas.map(d => d.property),\n }));\n\n return ok({ presets, count: presets.length });\n },\n );\n}\n","// @a-company/atelier-mcp — Validation and preview tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { validateDocument } from \"@a-company/atelier-schema\";\nimport { validateAllDeltas, resolveFrame } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_validate ────────────────────────────────────────\n server.tool(\n \"atelier_validate\",\n \"Validate an Atelier document for schema correctness and delta overlaps\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n // Schema validation\n const schemaResult = validateDocument(doc);\n const schemaErrors = schemaResult.success ? [] : schemaResult.errors;\n\n // Overlap validation per state\n const overlapErrors: Array<{ state: string; message: string }> = [];\n for (const [stateName, state] of Object.entries(doc.states)) {\n const overlaps = validateAllDeltas(state.deltas);\n for (const overlap of overlaps) {\n overlapErrors.push({ state: stateName, message: overlap.message });\n }\n }\n\n const valid = schemaErrors.length === 0 && overlapErrors.length === 0;\n\n return ok({\n valid,\n schemaErrors,\n overlapErrors,\n summary: valid\n ? \"Document is valid\"\n : `Found ${schemaErrors.length} schema error(s) and ${overlapErrors.length} overlap error(s)`,\n });\n },\n );\n\n // ── atelier_preview ─────────────────────────────────────────\n server.tool(\n \"atelier_preview\",\n \"Preview the resolved state of all layers at a specific frame\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to preview\"),\n frame: z.number().int().min(0).describe(\"Frame number to resolve\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frame }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) {\n return err(`State \"${stateName}\" not found`);\n }\n\n try {\n const resolved = resolveFrame(doc, stateName, frame);\n\n const layers = resolved.layers.map(rl => ({\n id: rl.id,\n visualType: rl.layer.visual.type,\n baseFrame: rl.layer.frame,\n baseBounds: rl.layer.bounds,\n baseOpacity: rl.layer.opacity,\n baseRotation: rl.layer.rotation,\n computedProperties: rl.computedProperties,\n }));\n\n return ok({\n stateName: resolved.stateName,\n frame: resolved.frame,\n duration: doc.states[stateName].duration,\n layers,\n });\n } catch (e) {\n return err(`Preview failed: ${(e as Error).message}`);\n }\n },\n );\n}\n","// @a-company/atelier-mcp — Template variable tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { instantiateTemplate, findTemplateVariables } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_instantiate_template ──────────────────────────────\n server.tool(\n \"atelier_instantiate_template\",\n \"Instantiate a template document with variable bindings. Creates a new document in the store.\",\n {\n id: z.string().describe(\"Template document ID\"),\n bindings: z.record(z.unknown()).describe(\"Variable bindings: { variableName: value }\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, bindings }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const templateResult = instantiateTemplate(doc, bindings);\n\n if (!templateResult.success) {\n return err(`Template errors: ${templateResult.errors.map(e => `${e.variable}: ${e.message}`).join(\"; \")}`);\n }\n\n const newId = store.create(templateResult.document);\n return ok({\n id: newId,\n name: templateResult.document.name,\n message: \"Template instantiated successfully\",\n });\n },\n );\n\n // ── atelier_find_variables ────────────────────────────────────\n server.tool(\n \"atelier_find_variables\",\n \"Scan a document for {{variableName}} patterns. Returns the list of variable references found.\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const variables = findTemplateVariables(doc);\n const declared = doc.variables ? Object.keys(doc.variables) : [];\n\n return ok({\n variables,\n declared,\n undeclared: variables.filter(v => !declared.includes(v)),\n unused: declared.filter(d => !variables.includes(d)),\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Layer effect tools (blend mode, shadow, motion path, clip path, visual editing)\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n AtelierDocument,\n ShapeVisual,\n TextVisual,\n ImageVisual,\n} from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_set_blend_mode ────────────────────────────────\n server.tool(\n \"atelier_set_blend_mode\",\n \"Set or clear the blend mode on a layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n blendMode: z.enum([\n \"normal\", \"multiply\", \"screen\", \"overlay\", \"darken\", \"lighten\",\n \"color-dodge\", \"color-burn\", \"hard-light\", \"soft-light\",\n \"difference\", \"exclusion\", \"hue\", \"saturation\", \"color\", \"luminosity\",\n ]).nullable().describe(\"Blend mode to set, or null to clear\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, blendMode }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (blendMode === null) {\n delete layer.blendMode;\n return ok({ layerId, blendMode: null, cleared: true });\n }\n\n layer.blendMode = blendMode;\n return ok({ layerId, blendMode });\n },\n );\n\n // ── atelier_set_shadow ────────────────────────────────────\n server.tool(\n \"atelier_set_shadow\",\n \"Set or remove a drop shadow on a layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n shadow: z.object({\n color: z.unknown().describe(\"Shadow color (hex string or RGBA/HSLA object)\"),\n blur: z.number().min(0).describe(\"Blur radius in pixels\"),\n offsetX: z.number().optional().describe(\"Horizontal offset in pixels\"),\n offsetY: z.number().optional().describe(\"Vertical offset in pixels\"),\n }).nullable().describe(\"Shadow definition, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, shadow }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (shadow === null) {\n delete layer.shadow;\n return ok({ layerId, shadow: null, removed: true });\n }\n\n layer.shadow = shadow as unknown as NonNullable<typeof layer.shadow>;\n return ok({ layerId, hasShadow: true });\n },\n );\n\n // ── atelier_set_tint ─────────────────────────────────────\n server.tool(\n \"atelier_set_tint\",\n \"Set or remove a color tint on a layer (works on any visual type)\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n tint: z.object({\n color: z.string().describe(\"Tint color (hex string)\"),\n amount: z.number().min(0).max(1).describe(\"Tint amount (0 = none, 1 = full)\"),\n }).nullable().describe(\"Tint definition, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, tint }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (tint === null) {\n delete layer.tint;\n return ok({ layerId, tint: null, removed: true });\n }\n\n layer.tint = tint;\n return ok({ layerId, hasTint: true });\n },\n );\n\n // ── atelier_set_motion_path ───────────────────────────────\n server.tool(\n \"atelier_set_motion_path\",\n \"Set or remove a motion path on a layer for path-based position animation\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n motionPath: z.object({\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).min(2).describe(\"Path points (minimum 2)\"),\n closed: z.boolean().optional().describe(\"Whether the path is closed\"),\n autoRotate: z.boolean().optional().describe(\"Auto-rotate layer to follow path tangent\"),\n autoRotateOffset: z.number().optional().describe(\"Rotation offset in degrees when autoRotate is enabled\"),\n }).nullable().describe(\"Motion path definition, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, motionPath }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (motionPath === null) {\n delete layer.motionPath;\n return ok({ layerId, motionPath: null, removed: true });\n }\n\n layer.motionPath = motionPath as unknown as NonNullable<typeof layer.motionPath>;\n return ok({ layerId, pointCount: motionPath.points.length, closed: motionPath.closed ?? false });\n },\n );\n\n // ── atelier_set_clip_path ─────────────────────────────────\n server.tool(\n \"atelier_set_clip_path\",\n \"Set or remove a clip path on a layer to restrict rendering to within a shape\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n clipPath: z.object({\n type: z.enum([\"rect\", \"ellipse\", \"path\"]).describe(\"Clip shape type\"),\n cornerRadius: z.union([\n z.number(),\n z.tuple([z.number(), z.number(), z.number(), z.number()]),\n ]).optional().describe(\"Corner radius (rect only)\"),\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).optional().describe(\"Path points (path only)\"),\n closed: z.boolean().optional().describe(\"Whether path is closed (path only)\"),\n }).nullable().describe(\"Clip path shape, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, clipPath }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (clipPath === null) {\n delete layer.clipPath;\n return ok({ layerId, clipPath: null, removed: true });\n }\n\n layer.clipPath = clipPath as unknown as NonNullable<typeof layer.clipPath>;\n return ok({ layerId, clipType: clipPath.type });\n },\n );\n\n // ── atelier_edit_visual ───────────────────────────────────\n server.tool(\n \"atelier_edit_visual\",\n \"Edit visual content of an existing layer (text content/style, image src/assetId, shape/fill/stroke)\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n // Text fields\n content: z.string().optional().describe(\"New text content (text layers only)\"),\n style: z.record(z.unknown()).optional().describe(\"Partial style update — only provided keys are overwritten (text layers only)\"),\n // Image fields\n src: z.string().optional().describe(\"Image source URL (image layers only)\"),\n assetId: z.string().optional().describe(\"Asset ID reference (image layers only)\"),\n sourceRect: z.object({\n x: z.number(), y: z.number(), width: z.number().positive(), height: z.number().positive(),\n }).nullable().optional().describe(\"Source rectangle crop (image layers only). Null to remove.\"),\n spritesheet: z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n }).nullable().optional().describe(\"Spritesheet config (image layers only). Null to remove.\"),\n frameIndex: z.number().int().min(0).optional().describe(\"Spritesheet frame index (image layers only)\"),\n // Shape fields\n shape: z.object({\n type: z.enum([\"rect\", \"ellipse\", \"path\"]),\n cornerRadius: z.union([\n z.number(),\n z.tuple([z.number(), z.number(), z.number(), z.number()]),\n ]).optional(),\n points: z.array(z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n })).optional(),\n closed: z.boolean().optional(),\n }).optional().describe(\"New shape (shape layers only)\"),\n fill: z.record(z.unknown()).optional().describe(\"New fill definition (shape layers only)\"),\n stroke: z.record(z.unknown()).optional().describe(\"New stroke definition (shape layers only)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, content, style, src, assetId, sourceRect, spritesheet, frameIndex, shape, fill, stroke }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n const visualType = layer.visual.type;\n const updated: string[] = [];\n\n // Text fields\n if (content !== undefined) {\n if (visualType !== \"text\") return err(`Cannot set \"content\" on ${visualType} layer — text layers only`);\n (layer.visual as TextVisual).content = content;\n updated.push(\"content\");\n }\n if (style !== undefined) {\n if (visualType !== \"text\") return err(`Cannot set \"style\" on ${visualType} layer — text layers only`);\n const currentStyle = (layer.visual as TextVisual).style;\n Object.assign(currentStyle, style);\n updated.push(\"style\");\n }\n\n // Image fields\n if (src !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"src\" on ${visualType} layer — image layers only`);\n (layer.visual as ImageVisual).src = src;\n updated.push(\"src\");\n }\n if (assetId !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"assetId\" on ${visualType} layer — image layers only`);\n (layer.visual as ImageVisual).assetId = assetId;\n updated.push(\"assetId\");\n }\n if (sourceRect !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"sourceRect\" on ${visualType} layer — image layers only`);\n if (sourceRect === null) {\n delete (layer.visual as ImageVisual).sourceRect;\n updated.push(\"sourceRect (removed)\");\n } else {\n (layer.visual as ImageVisual).sourceRect = sourceRect;\n updated.push(\"sourceRect\");\n }\n }\n if (spritesheet !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"spritesheet\" on ${visualType} layer — image layers only`);\n if (spritesheet === null) {\n delete (layer.visual as ImageVisual).spritesheet;\n updated.push(\"spritesheet (removed)\");\n } else {\n (layer.visual as ImageVisual).spritesheet = spritesheet;\n updated.push(\"spritesheet\");\n }\n }\n if (frameIndex !== undefined) {\n if (visualType !== \"image\") return err(`Cannot set \"frameIndex\" on ${visualType} layer — image layers only`);\n (layer.visual as ImageVisual).frameIndex = frameIndex;\n updated.push(\"frameIndex\");\n }\n\n // Shape fields\n if (shape !== undefined) {\n if (visualType !== \"shape\") return err(`Cannot set \"shape\" on ${visualType} layer — shape layers only`);\n (layer.visual as ShapeVisual).shape = shape as ShapeVisual[\"shape\"];\n updated.push(\"shape\");\n }\n if (fill !== undefined) {\n if (visualType !== \"shape\") return err(`Cannot set \"fill\" on ${visualType} layer — shape layers only`);\n (layer.visual as ShapeVisual).fill = fill as unknown as ShapeVisual[\"fill\"];\n updated.push(\"fill\");\n }\n if (stroke !== undefined) {\n if (visualType !== \"shape\") return err(`Cannot set \"stroke\" on ${visualType} layer — shape layers only`);\n (layer.visual as ShapeVisual).stroke = stroke as unknown as ShapeVisual[\"stroke\"];\n updated.push(\"stroke\");\n }\n\n if (updated.length === 0) {\n return err(\"No visual fields provided to update\");\n }\n\n return ok({ layerId, visualType, updated });\n },\n );\n}\n","// @a-company/atelier-mcp — State configuration tools (audio, transitions, parent states)\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nconst EasingInputSchema = z.union([\n z.enum([\"ease-in\", \"ease-out\", \"ease-in-out\"]),\n z.object({ type: z.literal(\"linear\") }),\n z.object({\n type: z.literal(\"cubic-bezier\"),\n x1: z.number(), y1: z.number(), x2: z.number(), y2: z.number(),\n }),\n z.object({\n type: z.literal(\"spring\"),\n mass: z.number().optional(),\n stiffness: z.number().optional(),\n damping: z.number().optional(),\n velocity: z.number().optional(),\n }),\n z.object({\n type: z.literal(\"step\"),\n steps: z.number().int().positive(),\n position: z.enum([\"start\", \"end\"]).optional(),\n }),\n]).describe(\"Easing function\");\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // NOTE: `atelier_set_audio` was removed in v1.0. Audio is now a first-class\n // `AudioVisual` layer (not a per-state field). Add audio via the unified\n // clip-authoring path: `atelier_add_clip` with `kind: \"audio\"`. State\n // configuration tools below still operate on transitions and state\n // metadata; audio is no longer state-scoped.\n\n // ── atelier_configure_transition ──────────────────────────\n server.tool(\n \"atelier_configure_transition\",\n \"Configure or remove a transition from one state to a target state\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"Source state name\"),\n targetState: z.string().describe(\"Target state name\"),\n transition: z.object({\n duration: z.number().positive().int().describe(\"Transition duration in frames\"),\n easing: EasingInputSchema.optional(),\n }).nullable().describe(\"Transition config, or null to remove\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, targetState, transition }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (stateName === targetState) {\n return err(\"Cannot create a transition from a state to itself\");\n }\n\n if (!doc.states[targetState]) {\n return err(`Target state \"${targetState}\" not found`);\n }\n\n if (transition === null) {\n if (state.transitions) {\n delete state.transitions[targetState];\n if (Object.keys(state.transitions).length === 0) {\n delete state.transitions;\n }\n }\n return ok({ stateName, targetState, removed: true });\n }\n\n if (!state.transitions) {\n state.transitions = {};\n }\n state.transitions[targetState] = transition as unknown as NonNullable<typeof state.transitions>[string];\n return ok({ stateName, targetState, duration: transition.duration });\n },\n );\n\n // ── atelier_set_state_parent ──────────────────────────────\n server.tool(\n \"atelier_set_state_parent\",\n \"Set or clear the parent state for hierarchical delta inheritance\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n parent: z.string().nullable().describe(\"Parent state name, or null to clear\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, stateName, parent }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const state = doc.states[stateName];\n if (!state) return err(`State \"${stateName}\" not found`);\n\n if (parent === null) {\n delete state.parent;\n return ok({ stateName, parent: null, cleared: true });\n }\n\n if (parent === stateName) {\n return err(\"A state cannot be its own parent\");\n }\n\n if (!doc.states[parent]) {\n return err(`Parent state \"${parent}\" not found`);\n }\n\n // Walk parent chain to detect cycles\n let current = parent;\n const visited = new Set<string>([stateName]);\n while (current) {\n if (visited.has(current)) {\n return err(`Circular reference detected: setting parent \"${parent}\" would create a cycle`);\n }\n visited.add(current);\n current = doc.states[current]?.parent as string;\n }\n\n state.parent = parent;\n return ok({ stateName, parent });\n },\n );\n}\n","// @a-company/atelier-mcp — Export tools (SVG, Lottie)\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { renderFrameSVG } from \"@a-company/atelier-svg\";\nimport { exportToLottie } from \"@a-company/atelier-lottie\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_export_svg ────────────────────────────────────\n server.tool(\n \"atelier_export_svg\",\n \"Export a frame as an SVG string\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().optional().describe(\"State name (defaults to first state)\"),\n frame: z.number().int().min(0).optional().describe(\"Frame number (defaults to 0)\"),\n xmlDeclaration: z.boolean().optional().describe(\"Include XML declaration (default: false)\"),\n viewBox: z.boolean().optional().describe(\"Include viewBox attribute (default: true)\"),\n indent: z.number().int().min(0).optional().describe(\"Indent size in spaces (default: 2)\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frame, xmlDeclaration, viewBox, indent }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) {\n return err(\"Document has no states\");\n }\n\n const resolvedStateName = stateName ?? stateNames[0];\n if (!doc.states[resolvedStateName]) {\n return err(`State \"${resolvedStateName}\" not found`);\n }\n\n try {\n const svg = renderFrameSVG(doc, resolvedStateName, frame ?? 0, {\n xmlDeclaration,\n viewBox,\n indent,\n });\n return ok({ svg, stateName: resolvedStateName, frame: frame ?? 0 });\n } catch (e) {\n return err((e as Error).message);\n }\n },\n );\n\n // ── atelier_export_lottie ─────────────────────────────────\n server.tool(\n \"atelier_export_lottie\",\n \"Export a document to Lottie JSON format (lossy, best-effort)\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().optional().describe(\"State to export (defaults to first state)\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n try {\n const { json, warnings } = exportToLottie(doc, {\n state: stateName,\n });\n return ok({ lottie: json as unknown as Record<string, unknown>, warnings });\n } catch (e) {\n return err((e as Error).message);\n }\n },\n );\n}\n","import type { Fill, Stroke, Color, RGBAColor, HSLAColor } from \"@a-company/atelier-types\";\nimport type { RenderContext } from \"./canvas-types.js\";\n\n/**\n * Convert an Atelier Color to a CSS color string.\n */\nexport function colorToCSS(color: Color): string {\n if (typeof color === \"string\") return color; // hex string\n\n if (\"r\" in color) {\n const c = color as RGBAColor;\n return `rgba(${Math.round(c.r)}, ${Math.round(c.g)}, ${Math.round(c.b)}, ${c.a})`;\n }\n\n if (\"h\" in color) {\n const c = color as HSLAColor;\n return `hsla(${c.h}, ${c.s}%, ${c.l}%, ${c.a})`;\n }\n\n return \"#000000\";\n}\n\n/**\n * Apply a Fill to the canvas context's fillStyle.\n */\nexport function applyFill(ctx: RenderContext, fill: Fill, width: number, height: number): void {\n switch (fill.type) {\n case \"solid\":\n ctx.fillStyle = colorToCSS(fill.color);\n break;\n\n case \"linear-gradient\": {\n const rad = (fill.angle * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const halfW = width / 2;\n const halfH = height / 2;\n const grad = ctx.createLinearGradient(\n halfW - cos * halfW, halfH - sin * halfH,\n halfW + cos * halfW, halfH + sin * halfH,\n );\n for (const stop of fill.stops) {\n grad.addColorStop(stop.offset, colorToCSS(stop.color));\n }\n ctx.fillStyle = grad as unknown as string;\n break;\n }\n\n case \"radial-gradient\": {\n const cx = typeof fill.center.x === \"number\" ? fill.center.x : (parseFloat(fill.center.x) / 100) * width;\n const cy = typeof fill.center.y === \"number\" ? fill.center.y : (parseFloat(fill.center.y) / 100) * height;\n const r = typeof fill.radius === \"number\" ? fill.radius : (parseFloat(fill.radius) / 100) * Math.max(width, height);\n const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, r);\n for (const stop of fill.stops) {\n grad.addColorStop(stop.offset, colorToCSS(stop.color));\n }\n ctx.fillStyle = grad as unknown as string;\n break;\n }\n }\n}\n\n/**\n * Apply a Stroke to the canvas context.\n * @param pathLength - total perimeter of the shape (needed for strokeStart/strokeEnd trim)\n */\nexport function applyStroke(ctx: RenderContext, stroke: Stroke, pathLength: number): void {\n ctx.strokeStyle = colorToCSS(stroke.color);\n ctx.lineWidth = stroke.width;\n if (stroke.lineCap) ctx.lineCap = stroke.lineCap;\n if (stroke.lineJoin) ctx.lineJoin = stroke.lineJoin;\n\n const start = stroke.strokeStart ?? 0;\n const end = stroke.strokeEnd ?? 1;\n\n if (start !== 0 || end !== 1) {\n const visible = (end - start) * pathLength;\n ctx.setLineDash([Math.max(visible, 0), pathLength + 1]);\n ctx.lineDashOffset = -start * pathLength;\n } else if (stroke.dash) {\n ctx.setLineDash(stroke.dash);\n }\n}\n","import type { Layer, Visual, ShapeVisual, TextVisual, ImageVisual, Color, BlendMode, LinearGradientFill, RadialGradientFill } from \"@a-company/atelier-types\";\nimport { colorToCSS } from \"./styles.js\";\nimport { evaluatePathAtProgress } from \"@a-company/atelier-math\";\nimport type { ResolvedLayer } from \"@a-company/atelier-core\";\n\n/**\n * Effective values for a layer at a given frame,\n * with computed properties merged over defaults.\n */\nexport interface EffectiveLayer {\n /** Original layer */\n layer: Layer;\n /** Visual with animated property overrides applied */\n visual: Visual;\n /** Effective frame position (may be animated) */\n x: number;\n y: number;\n /** Effective bounds */\n width: number;\n height: number;\n /** Effective transform values */\n opacity: number;\n rotation: number;\n scaleX: number;\n scaleY: number;\n anchorX: number;\n anchorY: number;\n /** Resolved shadow (if layer has shadow or shadow is animated) */\n shadow?: {\n color: string;\n blur: number;\n offsetX: number;\n offsetY: number;\n };\n /** Blend mode for compositing */\n blendMode: string;\n /** Motion path auto-rotation in degrees (applied additively to rotation) */\n motionPathAngle: number;\n /** Whether this layer is visible (may be animated) */\n visible: boolean;\n /** Color tint overlay */\n tint?: {\n color: string;\n amount: number;\n };\n}\n\n/**\n * Resolve a UnitValue to pixels. Percentages resolve against a reference dimension.\n */\nfunction resolveUnit(value: number | string, reference: number): number {\n if (typeof value === \"string\" && value.endsWith(\"%\")) {\n return (parseFloat(value) / 100) * reference;\n }\n return value as number;\n}\n\n/**\n * Build the effective layer values by merging computed properties over layer defaults.\n * @param resolved - The resolved layer from frame resolution\n * @param parentWidth - Parent/canvas width for percentage resolution\n * @param parentHeight - Parent/canvas height for percentage resolution\n */\nexport function buildEffectiveLayer(\n resolved: ResolvedLayer,\n parentWidth: number,\n parentHeight: number,\n): EffectiveLayer {\n const { layer, computedProperties } = resolved;\n const cp = computedProperties as Record<string, unknown>;\n\n const hasShadow = layer.shadow || cp[\"shadow.blur\"] !== undefined || cp[\"shadow.color\"] !== undefined;\n const hasTint = layer.tint || cp[\"tint.amount\"] !== undefined || cp[\"tint.color\"] !== undefined;\n\n // Resolve base position\n let x = resolveUnit((cp[\"frame.x\"] ?? layer.frame.x) as number | string, parentWidth);\n let y = resolveUnit((cp[\"frame.y\"] ?? layer.frame.y) as number | string, parentHeight);\n let motionPathAngle = 0;\n\n // Motion path overrides position when progress is animated\n const motionProgress = cp[\"motionPath.progress\"] as number | undefined;\n if (motionProgress !== undefined && layer.motionPath && layer.motionPath.points.length >= 2) {\n const pos = evaluatePathAtProgress(layer.motionPath.points, motionProgress, layer.motionPath.closed);\n x = pos.x;\n y = pos.y;\n if (layer.motionPath.autoRotate) {\n motionPathAngle = pos.angle + (layer.motionPath.autoRotateOffset ?? 0);\n }\n }\n\n return {\n layer,\n visual: buildEffectiveVisual(layer.visual, cp),\n x,\n y,\n width: resolveUnit((cp[\"bounds.width\"] ?? layer.bounds.width) as number | string, parentWidth),\n height: resolveUnit((cp[\"bounds.height\"] ?? layer.bounds.height) as number | string, parentHeight),\n opacity: (cp[\"opacity\"] as number) ?? layer.opacity ?? 1,\n rotation: (cp[\"rotation\"] as number) ?? layer.rotation ?? 0,\n scaleX: (cp[\"scale.x\"] as number) ?? layer.scale?.x ?? 1,\n scaleY: (cp[\"scale.y\"] as number) ?? layer.scale?.y ?? 1,\n anchorX: (cp[\"anchorPoint.x\"] as number) ?? layer.anchorPoint?.x ?? 0,\n anchorY: (cp[\"anchorPoint.y\"] as number) ?? layer.anchorPoint?.y ?? 0,\n shadow: hasShadow ? {\n color: colorToCSS((cp[\"shadow.color\"] ?? layer.shadow?.color ?? \"#00000080\") as Color),\n blur: (cp[\"shadow.blur\"] as number) ?? layer.shadow?.blur ?? 0,\n offsetX: (cp[\"shadow.offsetX\"] as number) ?? layer.shadow?.offsetX ?? 0,\n offsetY: (cp[\"shadow.offsetY\"] as number) ?? layer.shadow?.offsetY ?? 0,\n } : undefined,\n blendMode: (layer.blendMode as BlendMode) ?? \"normal\",\n motionPathAngle,\n visible: (cp[\"visible\"] as boolean) ?? layer.visible ?? true,\n tint: hasTint ? {\n color: colorToCSS((cp[\"tint.color\"] ?? layer.tint?.color ?? \"#FF0000\") as Color),\n amount: (cp[\"tint.amount\"] as number) ?? layer.tint?.amount ?? 0,\n } : undefined,\n };\n}\n\n/**\n * Build an effective visual by applying computed property overrides.\n * Returns the original visual if no visual properties are animated.\n */\nfunction buildEffectiveVisual(visual: Visual, cp: Record<string, unknown>): Visual {\n const hasVisualOverride =\n cp[\"visual.fill.color\"] !== undefined ||\n cp[\"visual.fill.angle\"] !== undefined ||\n cp[\"visual.fill.center.x\"] !== undefined ||\n cp[\"visual.fill.center.y\"] !== undefined ||\n cp[\"visual.fill.radius\"] !== undefined ||\n cp[\"visual.stroke.color\"] !== undefined ||\n cp[\"visual.stroke.width\"] !== undefined ||\n cp[\"visual.stroke.start\"] !== undefined ||\n cp[\"visual.stroke.end\"] !== undefined ||\n cp[\"visual.shape.cornerRadius\"] !== undefined ||\n cp[\"visual.style.fontSize\"] !== undefined ||\n cp[\"visual.style.color\"] !== undefined;\n\n const hasImageOverride =\n cp[\"visual.image.sourceRect.x\"] !== undefined ||\n cp[\"visual.image.sourceRect.y\"] !== undefined ||\n cp[\"visual.image.sourceRect.width\"] !== undefined ||\n cp[\"visual.image.sourceRect.height\"] !== undefined ||\n cp[\"visual.image.frameIndex\"] !== undefined;\n\n if (!hasVisualOverride && !hasImageOverride) return visual;\n\n if (visual.type === \"shape\") {\n const v: ShapeVisual = { ...visual };\n\n if (cp[\"visual.shape.cornerRadius\"] !== undefined && v.shape.type === \"rect\") {\n v.shape = { ...v.shape, cornerRadius: cp[\"visual.shape.cornerRadius\"] as number };\n }\n\n if (v.fill) {\n if (cp[\"visual.fill.color\"] !== undefined && v.fill.type === \"solid\") {\n v.fill = { ...v.fill, color: cp[\"visual.fill.color\"] as string };\n }\n if (cp[\"visual.fill.angle\"] !== undefined && v.fill.type === \"linear-gradient\") {\n v.fill = { ...v.fill, angle: cp[\"visual.fill.angle\"] as number } as LinearGradientFill;\n }\n if (v.fill.type === \"radial-gradient\") {\n const cx = cp[\"visual.fill.center.x\"];\n const cy = cp[\"visual.fill.center.y\"];\n const r = cp[\"visual.fill.radius\"];\n if (cx !== undefined || cy !== undefined || r !== undefined) {\n const f = v.fill as RadialGradientFill;\n v.fill = {\n ...f,\n center: {\n x: cx !== undefined ? (cx as number) : f.center.x,\n y: cy !== undefined ? (cy as number) : f.center.y,\n },\n radius: r !== undefined ? (r as number) : f.radius,\n } as RadialGradientFill;\n }\n }\n }\n\n if (v.stroke) {\n const strokeColor = cp[\"visual.stroke.color\"] ?? v.stroke.color;\n const strokeWidth = (cp[\"visual.stroke.width\"] as number) ?? v.stroke.width;\n const strokeStart = (cp[\"visual.stroke.start\"] as number | undefined) ?? v.stroke.strokeStart;\n const strokeEnd = (cp[\"visual.stroke.end\"] as number | undefined) ?? v.stroke.strokeEnd;\n if (\n strokeColor !== v.stroke.color ||\n strokeWidth !== v.stroke.width ||\n strokeStart !== v.stroke.strokeStart ||\n strokeEnd !== v.stroke.strokeEnd\n ) {\n v.stroke = {\n ...v.stroke,\n color: strokeColor as string,\n width: strokeWidth,\n strokeStart,\n strokeEnd,\n };\n }\n }\n\n return v;\n }\n\n if (visual.type === \"text\") {\n const v: TextVisual = { ...visual };\n const fontSize = (cp[\"visual.style.fontSize\"] as number) ?? v.style.fontSize;\n const color = cp[\"visual.style.color\"] ?? v.style.color;\n if (fontSize !== v.style.fontSize || color !== v.style.color) {\n v.style = { ...v.style, fontSize, color: color as string };\n }\n return v;\n }\n\n if (visual.type === \"image\" && hasImageOverride) {\n const v: ImageVisual = { ...visual };\n\n // Merge animated sourceRect fields\n if (\n cp[\"visual.image.sourceRect.x\"] !== undefined ||\n cp[\"visual.image.sourceRect.y\"] !== undefined ||\n cp[\"visual.image.sourceRect.width\"] !== undefined ||\n cp[\"visual.image.sourceRect.height\"] !== undefined\n ) {\n const base = v.sourceRect ?? { x: 0, y: 0, width: 0, height: 0 };\n v.sourceRect = {\n x: (cp[\"visual.image.sourceRect.x\"] as number) ?? base.x,\n y: (cp[\"visual.image.sourceRect.y\"] as number) ?? base.y,\n width: (cp[\"visual.image.sourceRect.width\"] as number) ?? base.width,\n height: (cp[\"visual.image.sourceRect.height\"] as number) ?? base.height,\n };\n }\n\n // Merge animated frameIndex\n if (cp[\"visual.image.frameIndex\"] !== undefined) {\n v.frameIndex = Math.floor(cp[\"visual.image.frameIndex\"] as number);\n }\n\n return v;\n }\n\n return visual;\n}\n","import type { ShapeVisual } from \"@a-company/atelier-types\";\nimport type { RenderContext } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\nimport { applyFill, applyStroke } from \"../styles.js\";\n\nexport function renderShape(ctx: RenderContext, eff: EffectiveLayer): void {\n const visual = eff.visual as ShapeVisual;\n const { shape } = visual;\n const { width, height } = eff;\n\n switch (shape.type) {\n case \"rect\":\n renderRect(ctx, width, height, shape.cornerRadius, visual);\n break;\n case \"ellipse\":\n renderEllipse(ctx, width, height, visual);\n break;\n case \"path\":\n renderPath(ctx, shape.points, shape.closed, visual);\n break;\n }\n}\n\n// ── Perimeter helpers ───────────────────────────────────────\n\nfunction rectPerimeter(w: number, h: number): number {\n return 2 * (w + h);\n}\n\nfunction ellipsePerimeter(w: number, h: number): number {\n const a = w / 2;\n const b = h / 2;\n // Ramanujan approximation\n return Math.PI * (3 * (a + b) - Math.sqrt((3 * a + b) * (a + 3 * b)));\n}\n\nfunction dist(x1: number, y1: number, x2: number, y2: number): number {\n const dx = x2 - x1;\n const dy = y2 - y1;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\nfunction pathPerimeter(\n points: { x: number; y: number; in?: { x: number; y: number }; out?: { x: number; y: number } }[],\n closed: boolean | undefined,\n): number {\n let length = 0;\n for (let i = 1; i < points.length; i++) {\n const prev = points[i - 1];\n const curr = points[i];\n if (prev.out && curr.in) {\n // Approximate bezier with chord * 1.2\n length += dist(prev.x, prev.y, curr.x, curr.y) * 1.2;\n } else {\n length += dist(prev.x, prev.y, curr.x, curr.y);\n }\n }\n if (closed && points.length > 1) {\n const first = points[0];\n const last = points[points.length - 1];\n length += dist(last.x, last.y, first.x, first.y);\n }\n return length;\n}\n\n// ── Renderers ───────────────────────────────────────────────\n\nfunction renderRect(\n ctx: RenderContext,\n width: number,\n height: number,\n cornerRadius: number | [number, number, number, number] | undefined,\n visual: ShapeVisual,\n): void {\n if (visual.fill) {\n applyFill(ctx, visual.fill, width, height);\n if (cornerRadius && ctx.roundRect) {\n ctx.beginPath();\n ctx.roundRect(0, 0, width, height, cornerRadius);\n ctx.fill();\n } else {\n ctx.fillRect(0, 0, width, height);\n }\n }\n if (visual.stroke) {\n const perimeter = rectPerimeter(width, height);\n applyStroke(ctx, visual.stroke, perimeter);\n if (cornerRadius && ctx.roundRect) {\n ctx.beginPath();\n ctx.roundRect(0, 0, width, height, cornerRadius);\n ctx.stroke();\n } else {\n ctx.strokeRect(0, 0, width, height);\n }\n }\n}\n\nfunction renderEllipse(\n ctx: RenderContext,\n width: number,\n height: number,\n visual: ShapeVisual,\n): void {\n ctx.beginPath();\n ctx.ellipse(width / 2, height / 2, width / 2, height / 2, 0, 0, Math.PI * 2);\n\n if (visual.fill) {\n applyFill(ctx, visual.fill, width, height);\n ctx.fill();\n }\n if (visual.stroke) {\n const perimeter = ellipsePerimeter(width, height);\n applyStroke(ctx, visual.stroke, perimeter);\n ctx.stroke();\n }\n}\n\nfunction renderPath(\n ctx: RenderContext,\n points: { x: number; y: number; in?: { x: number; y: number }; out?: { x: number; y: number } }[],\n closed: boolean | undefined,\n visual: ShapeVisual,\n): void {\n if (points.length < 2) return;\n\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n\n for (let i = 1; i < points.length; i++) {\n const prev = points[i - 1];\n const curr = points[i];\n\n if (prev.out && curr.in) {\n ctx.bezierCurveTo(\n prev.x + prev.out.x, prev.y + prev.out.y,\n curr.x + curr.in.x, curr.y + curr.in.y,\n curr.x, curr.y,\n );\n } else {\n ctx.lineTo(curr.x, curr.y);\n }\n }\n\n if (closed) ctx.closePath();\n\n if (visual.fill) {\n applyFill(ctx, visual.fill, 0, 0);\n ctx.fill();\n }\n if (visual.stroke) {\n const perimeter = pathPerimeter(points, closed);\n applyStroke(ctx, visual.stroke, perimeter);\n ctx.stroke();\n }\n}\n","import type { TextVisual } from \"@a-company/atelier-types\";\nimport type { RenderContext } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\nimport { colorToCSS } from \"../styles.js\";\n\nexport function renderText(ctx: RenderContext, eff: EffectiveLayer): void {\n const visual = eff.visual as TextVisual;\n const { style } = visual;\n\n // Build font string\n const fontStyle = style.fontStyle ?? \"normal\";\n const fontWeight = style.fontWeight ?? \"normal\";\n const fontSize = style.fontSize;\n const fontFamily = style.fontFamily;\n ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;\n\n // Set alignment — position text within its bounding box\n const align = style.textAlign ?? \"left\";\n ctx.textAlign = align;\n ctx.textBaseline = \"top\";\n\n // Set color\n ctx.fillStyle = colorToCSS(style.color);\n\n // Canvas 2D textAlign anchors at the draw point, so offset within bounds:\n // \"left\" → draw at x=0 (text flows right from left edge)\n // \"center\" → draw at x=width/2 (text centers within bounds)\n // \"right\" → draw at x=width (text flows left from right edge)\n let textX = 0;\n if (align === \"center\") {\n textX = eff.width / 2;\n } else if (align === \"right\") {\n textX = eff.width;\n }\n\n ctx.fillText(visual.content, textX, 0);\n}\n","import type { ImageVisual } from \"@a-company/atelier-types\";\nimport type { RenderContext } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\nimport type { ImageCache } from \"../image-cache.js\";\n\n/**\n * Render an image layer to the canvas.\n * Supports sourceRect cropping and spritesheet grid animation.\n * If the image hasn't loaded yet, triggers a cache load and returns\n * (the image will appear on the next re-render).\n */\nexport function renderImage(ctx: RenderContext, eff: EffectiveLayer, imageCache: ImageCache): void {\n const visual = eff.visual as ImageVisual;\n const src = visual.src;\n if (!src) return;\n\n const img = imageCache.get(src);\n if (!img) {\n imageCache.load(src);\n return;\n }\n\n // Spritesheet grid computation takes precedence over manual sourceRect\n if (visual.spritesheet) {\n const { columns, rows, frameWidth, frameHeight, frameCount } = visual.spritesheet;\n const maxFrames = frameCount ?? (columns * rows);\n const idx = Math.max(0, Math.min(Math.floor(visual.frameIndex ?? 0), maxFrames - 1));\n const col = idx % columns;\n const row = Math.floor(idx / columns);\n const sx = col * frameWidth;\n const sy = row * frameHeight;\n (ctx.drawImage as Function)(img, sx, sy, frameWidth, frameHeight, 0, 0, eff.width, eff.height);\n return;\n }\n\n // Manual sourceRect crop\n if (visual.sourceRect) {\n const sr = visual.sourceRect;\n (ctx.drawImage as Function)(img, sr.x, sr.y, sr.width, sr.height, 0, 0, eff.width, eff.height);\n return;\n }\n\n // Default: draw full image to bounds\n ctx.drawImage(img, 0, 0, eff.width, eff.height);\n}\n","import type { VideoVisual } from \"@a-company/atelier-types\";\nimport type { RenderContext, VideoFrameProvider } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\n\n/**\n * Render a video layer to the canvas at the given source time.\n * Delegates actual frame extraction to the injected VideoFrameProvider,\n * which may be backed by HTMLVideoElement (preview) or WebCodecs (export).\n * Returns without drawing if the provider returns null — caller retries next tick.\n *\n * Honors `visual.objectFit`:\n * - `\"fill\"` (default for legacy behavior) — stretch to layer bounds, may distort.\n * - `\"contain\"` — aspect-preserving fit-inside, letterbox with transparent gutters.\n * - `\"cover\"` — aspect-preserving fill-outside, crop overflow.\n * The default is `contain` when omitted — for a creator authoring a 9:16\n * portrait canvas with a 16:9 source clip, `fill` would squash visibly;\n * `contain` shows the clip in its natural aspect within the layer's box.\n */\nexport function renderVideo(\n ctx: RenderContext,\n eff: EffectiveLayer,\n sourceTime: number,\n provider: VideoFrameProvider,\n): void {\n const visual = eff.visual as VideoVisual;\n const src = visual.src;\n if (!src) return;\n\n const frame = provider(src, sourceTime, eff.width, eff.height);\n if (!frame) return;\n\n const fit = visual.objectFit ?? \"contain\";\n if (fit === \"fill\") {\n ctx.drawImage(frame as unknown, 0, 0, eff.width, eff.height);\n return;\n }\n\n // Frame has natural dimensions — HTMLVideoElement carries videoWidth/Height,\n // ImageBitmap carries width/height. Both surface as `.width` / `.height` /\n // `.videoWidth` / `.videoHeight`. Probe at runtime; fall back to fill if we\n // can't read the source's intrinsic size (e.g. partially-loaded video).\n const src_w = (frame as { videoWidth?: number; width?: number }).videoWidth\n ?? (frame as { width?: number }).width\n ?? 0;\n const src_h = (frame as { videoHeight?: number; height?: number }).videoHeight\n ?? (frame as { height?: number }).height\n ?? 0;\n if (src_w <= 0 || src_h <= 0) {\n ctx.drawImage(frame as unknown, 0, 0, eff.width, eff.height);\n return;\n }\n\n const srcAspect = src_w / src_h;\n const dstAspect = eff.width / eff.height;\n let dw: number, dh: number, dx: number, dy: number;\n\n if (fit === \"cover\") {\n // Fill the box, overflow on the longer axis is cropped.\n if (srcAspect > dstAspect) {\n dh = eff.height;\n dw = dh * srcAspect;\n } else {\n dw = eff.width;\n dh = dw / srcAspect;\n }\n } else {\n // contain — fit inside the box, transparent letterbox on the shorter axis.\n if (srcAspect > dstAspect) {\n dw = eff.width;\n dh = dw / srcAspect;\n } else {\n dh = eff.height;\n dw = dh * srcAspect;\n }\n }\n dx = (eff.width - dw) / 2;\n dy = (eff.height - dh) / 2;\n ctx.drawImage(frame as unknown, dx, dy, dw, dh);\n}\n","import type { AtelierDocument, RefVisual, ImageVisual } from \"@a-company/atelier-types\";\nimport { resolveFrame } from \"@a-company/atelier-core\";\nimport type { RenderContext, DocumentResolver } from \"../canvas-types.js\";\nimport type { EffectiveLayer } from \"../apply-properties.js\";\nimport { buildEffectiveLayer } from \"../apply-properties.js\";\nimport { renderShape } from \"./shape-renderer.js\";\nimport { renderText } from \"./text-renderer.js\";\nimport { renderImage } from \"./image-renderer.js\";\nimport type { ImageCache } from \"../image-cache.js\";\n\nexport interface RefRenderOpts {\n documentResolver?: DocumentResolver;\n maxRefDepth?: number;\n imageCache?: ImageCache;\n /** Internal: tracks visited refs for cycle detection */\n _visitedRefs?: Set<string>;\n /** Internal: current recursion depth */\n _depth?: number;\n}\n\n/**\n * Render a ref layer. If a documentResolver is provided, resolves and renders\n * the sub-document inline. Otherwise falls back to a placeholder rectangle.\n */\nexport function renderRef(\n ctx: RenderContext,\n eff: EffectiveLayer,\n opts?: RefRenderOpts,\n _parentDoc?: AtelierDocument,\n): void {\n const visual = eff.visual as RefVisual;\n const resolver = opts?.documentResolver;\n\n if (!resolver) {\n renderPlaceholder(ctx, eff, `REF: ${visual.src}`);\n return;\n }\n\n const depth = opts?._depth ?? 0;\n const maxDepth = opts?.maxRefDepth ?? 4;\n\n if (depth >= maxDepth) {\n renderPlaceholder(ctx, eff, \"MAX DEPTH\");\n return;\n }\n\n const visitedRefs = opts?._visitedRefs ?? new Set<string>();\n\n if (visitedRefs.has(visual.src)) {\n renderPlaceholder(ctx, eff, \"CYCLE\");\n return;\n }\n\n const subDoc = resolver(visual.src);\n if (!subDoc) {\n renderPlaceholder(ctx, eff, \"NOT FOUND\");\n return;\n }\n\n // Determine which state and frame to render\n const stateNames = Object.keys(subDoc.states);\n if (stateNames.length === 0) {\n renderPlaceholder(ctx, eff, \"NO STATES\");\n return;\n }\n\n const stateName = visual.state ?? stateNames[0];\n const stateObj = subDoc.states[stateName];\n if (!stateObj) {\n renderPlaceholder(ctx, eff, `STATE? ${stateName}`);\n return;\n }\n\n const maxFrame = Math.max(0, stateObj.duration - 1);\n const frame = Math.min(visual.frame ?? 0, maxFrame);\n\n // Resolve the sub-document frame\n const resolved = resolveFrame(subDoc, stateName, frame);\n\n // Mark as visited for cycle detection\n visitedRefs.add(visual.src);\n\n // Scale to fit eff bounds\n const scaleX = eff.width / subDoc.canvas.width;\n const scaleY = eff.height / subDoc.canvas.height;\n\n ctx.save();\n ctx.scale(scaleX, scaleY);\n\n // Build and render sub-doc layers\n const { width: subW, height: subH } = subDoc.canvas;\n\n for (const resolvedLayer of resolved.layers) {\n const subEff = buildEffectiveLayer(resolvedLayer, subW, subH);\n\n if (!subEff.visible) continue;\n if (subEff.opacity <= 0) continue;\n\n // Resolve asset for images\n if (resolvedLayer.layer.visual.type === \"image\") {\n const iv = subEff.visual as ImageVisual;\n if (!iv.src && iv.assetId && subDoc.assets?.[iv.assetId]) {\n iv.src = subDoc.assets[iv.assetId].src;\n }\n }\n\n ctx.save();\n ctx.globalAlpha = subEff.opacity;\n ctx.translate(subEff.x, subEff.y);\n\n switch (resolvedLayer.layer.visual.type) {\n case \"shape\":\n renderShape(ctx, subEff);\n break;\n case \"text\":\n renderText(ctx, subEff);\n break;\n case \"image\":\n if (opts?.imageCache) renderImage(ctx, subEff, opts.imageCache);\n break;\n case \"ref\":\n renderRef(ctx, subEff, {\n ...opts,\n _visitedRefs: visitedRefs,\n _depth: depth + 1,\n }, subDoc);\n break;\n case \"group\":\n break;\n }\n\n ctx.restore();\n }\n\n ctx.restore();\n\n // Remove from visited after rendering (allow same ref in different branches)\n visitedRefs.delete(visual.src);\n}\n\n/** Render a dashed placeholder rectangle with label */\nfunction renderPlaceholder(ctx: RenderContext, eff: EffectiveLayer, label: string): void {\n const { width, height } = eff;\n\n ctx.strokeStyle = \"#888888\";\n ctx.lineWidth = 2;\n ctx.setLineDash([6, 4]);\n ctx.strokeRect(0, 0, width, height);\n ctx.setLineDash([]);\n\n ctx.fillStyle = \"#888888\";\n ctx.font = `${Math.max(12, Math.min(16, height * 0.15))}px sans-serif`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n ctx.fillText(label, width / 2, height / 2, width - 8);\n}\n","import type { AtelierDocument, ImageVisual, VideoVisual, Shape } from \"@a-company/atelier-types\";\nimport type { ResolvedFrame } from \"@a-company/atelier-core\";\nimport type { RenderContext, DocumentResolver, VideoFrameProvider } from \"./canvas-types.js\";\nimport { buildEffectiveLayer, type EffectiveLayer } from \"./apply-properties.js\";\nimport { renderShape } from \"./renderers/shape-renderer.js\";\nimport { renderText } from \"./renderers/text-renderer.js\";\nimport { renderImage } from \"./renderers/image-renderer.js\";\nimport { renderVideo } from \"./renderers/video-renderer.js\";\nimport { renderRef } from \"./renderers/ref-renderer.js\";\nimport type { ImageCache } from \"./image-cache.js\";\n\n/** Options for renderFrame */\nexport interface RenderOptions {\n imageCache?: ImageCache;\n documentResolver?: DocumentResolver;\n maxRefDepth?: number;\n videoFrameProvider?: VideoFrameProvider;\n}\n\n/**\n * Render a resolved frame to a Canvas 2D context.\n * Clears the canvas and draws all visible layers in order.\n */\nexport function renderFrame(\n ctx: RenderContext,\n resolvedFrame: ResolvedFrame,\n doc: AtelierDocument,\n optsOrCache?: RenderOptions | ImageCache,\n): void {\n // Backward compatible: detect old ImageCache arg vs new RenderOptions\n let imageCache: ImageCache | undefined;\n let documentResolver: DocumentResolver | undefined;\n let videoFrameProvider: VideoFrameProvider | undefined;\n let maxRefDepth = 4;\n\n if (optsOrCache && typeof (optsOrCache as ImageCache).get === \"function\") {\n imageCache = optsOrCache as ImageCache;\n } else if (optsOrCache) {\n const opts = optsOrCache as RenderOptions;\n imageCache = opts.imageCache;\n documentResolver = opts.documentResolver;\n videoFrameProvider = opts.videoFrameProvider;\n maxRefDepth = opts.maxRefDepth ?? 4;\n }\n const { width, height } = doc.canvas;\n\n // Clear canvas, then apply background if explicitly set.\n //\n // The naive `fillStyle = \"transparent\"; fillRect(...)` was a NO-OP under\n // default `source-over` compositing — transparent pixels source-over\n // existing pixels = existing pixels unchanged. The canvas accumulated\n // content between renders, which was MASKED in the live editor by\n // full-canvas video layers (drawImage overwrites every pixel) but exposed\n // catastrophically in the MP4 exporter, where captions stacked up over\n // every frame because nothing else ever overwrote them (export had no\n // videoFrameProvider wired, so the video layer was a no-op). Owner saw\n // a \"single static frame with all captions overlapping\" in\n // /Users/ascend/Downloads/animation (1).mp4.\n //\n // `clearRect` resets every pixel to fully-transparent black regardless of\n // compositing. Then we fill the explicit background if the doc set one\n // (image/video docs may set \"#000\" or a brand color so letterboxed gutters\n // aren't transparent).\n ctx.clearRect(0, 0, width, height);\n if (doc.canvas.background) {\n ctx.fillStyle = doc.canvas.background;\n ctx.fillRect(0, 0, width, height);\n }\n\n // Build effective layers into a map for ancestor transform lookups\n const effMap = new Map<string, EffectiveLayer>();\n const effList: EffectiveLayer[] = [];\n const videoSourceTimeMap = new Map<string, number>();\n\n for (const resolvedLayer of resolvedFrame.layers) {\n const eff = buildEffectiveLayer(resolvedLayer, width, height);\n effMap.set(resolvedLayer.layer.id, eff);\n effList.push(eff);\n if (resolvedLayer.videoSourceTime !== undefined) {\n videoSourceTimeMap.set(resolvedLayer.layer.id, resolvedLayer.videoSourceTime);\n }\n }\n\n // Render each layer in order (painters algorithm — first = back)\n for (const eff of effList) {\n const { layer } = eff;\n\n // Skip invisible layers\n if (!eff.visible) continue;\n\n // Skip fully transparent layers\n if (eff.opacity <= 0) continue;\n\n // Resolve assetId → src for image visuals\n if (layer.visual.type === \"image\") {\n const iv = eff.visual as ImageVisual;\n if (!iv.src && iv.assetId && doc.assets?.[iv.assetId]) {\n iv.src = doc.assets[iv.assetId].src;\n }\n }\n\n // Resolve assetId → src for video visuals\n if (layer.visual.type === \"video\") {\n const vv = eff.visual as VideoVisual;\n if (!vv.src && vv.assetId && doc.assets?.[vv.assetId]) {\n vv.src = doc.assets[vv.assetId].src;\n }\n }\n\n ctx.save();\n\n // Apply ancestor transforms (group/parent inheritance)\n applyAncestorTransforms(ctx, layer.id, effMap, doc);\n\n // Apply transforms\n ctx.globalAlpha = eff.opacity;\n\n // Apply blend mode\n if (eff.blendMode !== \"normal\") {\n ctx.globalCompositeOperation = blendModeToComposite(eff.blendMode);\n }\n\n ctx.translate(eff.x, eff.y);\n\n // Apply anchor-relative transforms\n const anchorPixelX = eff.anchorX * eff.width;\n const anchorPixelY = eff.anchorY * eff.height;\n\n // Combine explicit rotation with motion path auto-rotation\n const totalRotation = eff.rotation + eff.motionPathAngle;\n\n if (totalRotation !== 0 || eff.scaleX !== 1 || eff.scaleY !== 1) {\n ctx.translate(anchorPixelX, anchorPixelY);\n if (totalRotation !== 0) {\n ctx.rotate((totalRotation * Math.PI) / 180);\n }\n if (eff.scaleX !== 1 || eff.scaleY !== 1) {\n ctx.scale(eff.scaleX, eff.scaleY);\n }\n ctx.translate(-anchorPixelX, -anchorPixelY);\n }\n\n // Apply shadow if present\n if (eff.shadow) {\n ctx.shadowColor = eff.shadow.color;\n ctx.shadowBlur = eff.shadow.blur;\n ctx.shadowOffsetX = eff.shadow.offsetX;\n ctx.shadowOffsetY = eff.shadow.offsetY;\n }\n\n // Apply clip path if present\n if (layer.clipPath) {\n applyClipPath(ctx, layer.clipPath, eff.width, eff.height);\n }\n\n // Tint requires offscreen compositing — draw to offscreen if tint is active\n const hasTint = eff.tint && eff.tint.amount > 0 && ctx.createOffscreen;\n let renderCtx = ctx;\n let offscreen: { ctx: RenderContext; canvas: unknown } | null = null;\n\n if (hasTint) {\n offscreen = ctx.createOffscreen!(eff.width, eff.height);\n renderCtx = offscreen.ctx;\n }\n\n // Ref rendering options (passed through for sub-doc composition)\n const refOpts = { documentResolver, maxRefDepth, imageCache };\n\n // Dispatch to type-specific renderer\n switch (layer.visual.type) {\n case \"shape\":\n renderShape(renderCtx, eff);\n break;\n case \"text\":\n renderText(renderCtx, eff);\n break;\n case \"image\":\n if (imageCache) renderImage(renderCtx, eff, imageCache);\n break;\n case \"video\":\n if (videoFrameProvider) {\n renderVideo(renderCtx, eff, videoSourceTimeMap.get(layer.id) ?? 0, videoFrameProvider);\n }\n break;\n case \"group\":\n // Groups are structural containers — no visual output\n break;\n case \"ref\":\n renderRef(renderCtx, eff, refOpts, doc);\n break;\n }\n\n // Apply tint via multiply composite on offscreen canvas\n if (hasTint && offscreen && eff.tint) {\n const offCtx = offscreen.ctx;\n // Draw tint color over the content using multiply\n offCtx.save();\n offCtx.globalCompositeOperation = \"multiply\";\n offCtx.fillStyle = eff.tint.color;\n offCtx.fillRect(0, 0, eff.width, eff.height);\n offCtx.restore();\n\n // Clip to original content shape using destination-in\n offCtx.save();\n offCtx.globalCompositeOperation = \"destination-in\";\n // Re-render the content to create the alpha mask\n switch (layer.visual.type) {\n case \"shape\": renderShape(offCtx, eff); break;\n case \"text\": renderText(offCtx, eff); break;\n case \"image\": if (imageCache) renderImage(offCtx, eff, imageCache); break;\n case \"video\": if (videoFrameProvider) renderVideo(offCtx, eff, videoSourceTimeMap.get(layer.id) ?? 0, videoFrameProvider); break;\n case \"ref\": renderRef(offCtx, eff, refOpts, doc); break;\n }\n offCtx.restore();\n\n // Blend tinted offscreen back with original at tint.amount alpha\n // First draw original content\n switch (layer.visual.type) {\n case \"shape\": renderShape(ctx, eff); break;\n case \"text\": renderText(ctx, eff); break;\n case \"image\": if (imageCache) renderImage(ctx, eff, imageCache); break;\n case \"video\": if (videoFrameProvider) renderVideo(ctx, eff, videoSourceTimeMap.get(layer.id) ?? 0, videoFrameProvider); break;\n case \"ref\": renderRef(ctx, eff, refOpts, doc); break;\n }\n // Then overlay tinted version at tint amount\n const prevAlpha = ctx.globalAlpha;\n ctx.globalAlpha = eff.tint.amount;\n ctx.drawImage(offscreen.canvas, 0, 0, eff.width, eff.height);\n ctx.globalAlpha = prevAlpha;\n }\n\n ctx.restore();\n }\n}\n\n/** Apply a shape as a clipping region */\nfunction applyClipPath(ctx: RenderContext, shape: Shape, width: number, height: number): void {\n ctx.beginPath();\n switch (shape.type) {\n case \"rect\":\n if (shape.cornerRadius && ctx.roundRect) {\n ctx.roundRect(0, 0, width, height, shape.cornerRadius);\n } else {\n // Manual rect path for clipping (fillRect doesn't create a path)\n ctx.moveTo(0, 0);\n ctx.lineTo(width, 0);\n ctx.lineTo(width, height);\n ctx.lineTo(0, height);\n ctx.closePath();\n }\n break;\n case \"ellipse\":\n ctx.ellipse(width / 2, height / 2, width / 2, height / 2, 0, 0, Math.PI * 2);\n break;\n case \"path\":\n if (shape.points.length >= 2) {\n ctx.moveTo(shape.points[0].x, shape.points[0].y);\n for (let i = 1; i < shape.points.length; i++) {\n const prev = shape.points[i - 1];\n const curr = shape.points[i];\n if (prev.out && curr.in) {\n ctx.bezierCurveTo(\n prev.x + prev.out.x, prev.y + prev.out.y,\n curr.x + curr.in.x, curr.y + curr.in.y,\n curr.x, curr.y,\n );\n } else {\n ctx.lineTo(curr.x, curr.y);\n }\n }\n if (shape.closed) ctx.closePath();\n }\n break;\n }\n ctx.clip();\n}\n\n/** Map Atelier blend mode names to Canvas 2D globalCompositeOperation values */\nfunction blendModeToComposite(mode: string): string {\n const map: Record<string, string> = {\n \"multiply\": \"multiply\",\n \"screen\": \"screen\",\n \"overlay\": \"overlay\",\n \"darken\": \"darken\",\n \"lighten\": \"lighten\",\n \"color-dodge\": \"color-dodge\",\n \"color-burn\": \"color-burn\",\n \"hard-light\": \"hard-light\",\n \"soft-light\": \"soft-light\",\n \"difference\": \"difference\",\n \"exclusion\": \"exclusion\",\n \"hue\": \"hue\",\n \"saturation\": \"saturation\",\n \"color\": \"color\",\n \"luminosity\": \"luminosity\",\n };\n return map[mode] ?? \"source-over\";\n}\n\n/**\n * Walk the parentId chain and apply each ancestor's transforms.\n * This makes child layers inherit parent position/rotation/scale.\n */\nfunction applyAncestorTransforms(\n ctx: RenderContext,\n layerId: string,\n effMap: Map<string, EffectiveLayer>,\n doc: AtelierDocument,\n): void {\n // Collect ancestor chain (excluding self)\n const chain: EffectiveLayer[] = [];\n const layer = doc.layers.find((l) => l.id === layerId);\n let parentId = layer?.parentId;\n const visited = new Set<string>();\n\n while (parentId && !visited.has(parentId)) {\n visited.add(parentId);\n const parentEff = effMap.get(parentId);\n if (!parentEff) break;\n chain.push(parentEff);\n parentId = parentEff.layer.parentId;\n }\n\n // Apply from root ancestor down to direct parent\n for (let i = chain.length - 1; i >= 0; i--) {\n const p = chain[i];\n ctx.translate(p.x, p.y);\n\n const ax = p.anchorX * p.width;\n const ay = p.anchorY * p.height;\n\n if (p.rotation !== 0 || p.scaleX !== 1 || p.scaleY !== 1) {\n ctx.translate(ax, ay);\n if (p.rotation !== 0) ctx.rotate((p.rotation * Math.PI) / 180);\n if (p.scaleX !== 1 || p.scaleY !== 1) ctx.scale(p.scaleX, p.scaleY);\n ctx.translate(-ax, -ay);\n }\n }\n}\n","/**\n * A loaded image entry that can be drawn via RenderContext.drawImage.\n */\nexport interface CachedImage {\n complete: boolean;\n image: unknown;\n}\n\n/**\n * Simple image cache for loading and caching images.\n * Browser-agnostic — the actual Image constructor is injected via createImage.\n * Triggers an onLoad callback when an image finishes loading so the\n * renderer can re-render the current frame.\n */\nexport class ImageCache {\n private cache = new Map<string, CachedImage>();\n private loading = new Set<string>();\n private onLoad?: () => void;\n private createImage?: (src: string, onLoad: () => void, onError: () => void) => unknown;\n\n constructor(opts?: {\n onLoad?: () => void;\n createImage?: (src: string, onLoad: () => void, onError: () => void) => unknown;\n }) {\n this.onLoad = opts?.onLoad;\n this.createImage = opts?.createImage;\n }\n\n get(src: string): unknown | null {\n const entry = this.cache.get(src);\n return entry?.complete ? entry.image : null;\n }\n\n load(src: string): void {\n if (this.cache.has(src) || this.loading.has(src)) return;\n if (!this.createImage) return;\n this.loading.add(src);\n const image = this.createImage(\n src,\n () => {\n this.cache.set(src, { complete: true, image });\n this.loading.delete(src);\n this.onLoad?.();\n },\n () => {\n this.loading.delete(src);\n },\n );\n }\n}\n","import type { AtelierDocument, ImageVisual, RefVisual } from \"@a-company/atelier-types\";\nimport { resolveFrame, type ResolvedFrame } from \"@a-company/atelier-core\";\nimport { buildEffectiveLayer, type EffectiveLayer, type DocumentResolver } from \"@a-company/atelier-canvas\";\nimport { buildTransform, buildStyleAttrs } from \"./svg-properties.js\";\nimport { renderShapeSVG } from \"./svg-shapes.js\";\nimport { renderTextSVG } from \"./svg-text.js\";\nimport { buildShadowFilter, buildTintFilter, resetFilterCounter } from \"./svg-filters.js\";\nimport { resetGradientCounter } from \"./svg-gradients.js\";\nimport { buildClipPathDef, resetClipCounter } from \"./svg-clip.js\";\nimport { escapeXml } from \"./svg-properties.js\";\n\nexport interface RenderSVGOptions {\n /** Include XML declaration (default: false) */\n xmlDeclaration?: boolean;\n /** Include viewBox attribute (default: true) */\n viewBox?: boolean;\n /** Indent size in spaces (default: 2) */\n indent?: number;\n /** Resolves ref layer src paths to loaded AtelierDocuments */\n documentResolver?: DocumentResolver;\n /** Maximum ref nesting depth (default: 4) */\n maxRefDepth?: number;\n}\n\n/**\n * Render a resolved frame as an SVG string.\n * If no resolved frame is provided, resolves the given state and frame.\n */\nexport function renderFrameSVG(\n doc: AtelierDocument,\n stateOrFrame: string | ResolvedFrame,\n frame?: number,\n opts?: RenderSVGOptions,\n): string {\n // Reset counters for deterministic IDs\n resetGradientCounter();\n resetFilterCounter();\n resetClipCounter();\n\n let resolved: ResolvedFrame;\n if (typeof stateOrFrame === \"string\") {\n resolved = resolveFrame(doc, stateOrFrame, frame ?? 0);\n } else {\n resolved = stateOrFrame;\n }\n\n const { width, height } = doc.canvas;\n const indent = opts?.indent ?? 2;\n const pad = \" \".repeat(indent);\n\n // Build effective layers\n const effLayers: EffectiveLayer[] = resolved.layers.map(rl =>\n buildEffectiveLayer(rl, width, height),\n );\n\n // Collect all defs and layer elements\n const allDefs: string[] = [];\n const layerElements: string[] = [];\n\n for (let i = 0; i < effLayers.length; i++) {\n const eff = effLayers[i];\n const layer = resolved.layers[i].layer;\n\n // Skip invisible or fully transparent\n if (!eff.visible) continue;\n if (eff.opacity <= 0) continue;\n\n // Resolve asset for images\n if (layer.visual.type === \"image\") {\n const iv = eff.visual as ImageVisual;\n if (!iv.src && iv.assetId && doc.assets?.[iv.assetId]) {\n (eff.visual as ImageVisual).src = doc.assets[iv.assetId].src;\n }\n }\n\n // Build transform\n const transform = buildTransform(eff);\n const styleAttrs = buildStyleAttrs(eff);\n\n // Build shadow filter\n const filterResult = buildShadowFilter(eff);\n if (filterResult) allDefs.push(filterResult.defs);\n\n // Build tint filter\n const tintResult = buildTintFilter(eff);\n if (tintResult) allDefs.push(tintResult.defs);\n\n // Build clip path\n let clipAttr = \"\";\n if (layer.clipPath) {\n const clipResult = buildClipPathDef(layer.clipPath, eff.width, eff.height);\n if (clipResult.defs) {\n allDefs.push(clipResult.defs);\n clipAttr = ` clip-path=\"${clipResult.clipRef}\"`;\n }\n }\n\n // Build group attributes\n const gAttrs: string[] = [];\n if (transform) gAttrs.push(`transform=\"${transform}\"`);\n if (styleAttrs) gAttrs.push(styleAttrs);\n // Apply combined or individual filters\n if (filterResult && tintResult) {\n // When both shadow and tint exist, we need a combined filter\n // For simplicity, apply shadow filter and tint separately via style\n gAttrs.push(`filter=\"${filterResult.filterRef}\"`);\n // Tint is a second filter — wrap content in nested group\n } else if (filterResult) {\n gAttrs.push(`filter=\"${filterResult.filterRef}\"`);\n } else if (tintResult) {\n gAttrs.push(`filter=\"${tintResult.filterRef}\"`);\n }\n if (clipAttr) gAttrs.push(clipAttr.trim());\n\n // Render visual content\n let content = \"\";\n let layerDefs = \"\";\n\n switch (layer.visual.type) {\n case \"shape\": {\n const result = renderShapeSVG(eff, eff.visual as import(\"@a-company/atelier-types\").ShapeVisual);\n content = result.elements;\n layerDefs = result.defs;\n break;\n }\n case \"text\":\n content = renderTextSVG(eff, eff.visual as import(\"@a-company/atelier-types\").TextVisual);\n break;\n case \"image\": {\n const iv = eff.visual as ImageVisual;\n if (iv.src) {\n if (iv.spritesheet) {\n // Spritesheet: compute source rect and use full sheet dimensions for inner image\n const { columns, rows, frameWidth, frameHeight, frameCount } = iv.spritesheet;\n const maxFrames = frameCount ?? (columns * rows);\n const idx = Math.max(0, Math.min(Math.floor(iv.frameIndex ?? 0), maxFrames - 1));\n const col = idx % columns;\n const row = Math.floor(idx / columns);\n const sx = col * frameWidth;\n const sy = row * frameHeight;\n const imgW = columns * frameWidth;\n const imgH = rows * frameHeight;\n content = `<svg viewBox=\"${sx} ${sy} ${frameWidth} ${frameHeight}\" width=\"${eff.width}\" height=\"${eff.height}\">` +\n `<image href=\"${escapeXml(iv.src)}\" width=\"${imgW}\" height=\"${imgH}\" />` +\n `</svg>`;\n } else if (iv.sourceRect) {\n // Manual sourceRect: viewBox crops from image coordinate space\n const sr = iv.sourceRect;\n content = `<svg viewBox=\"${sr.x} ${sr.y} ${sr.width} ${sr.height}\" width=\"${eff.width}\" height=\"${eff.height}\">` +\n `<image href=\"${escapeXml(iv.src)}\" width=\"${eff.width}\" height=\"${eff.height}\" />` +\n `</svg>`;\n } else {\n content = `<image href=\"${escapeXml(iv.src)}\" width=\"${eff.width}\" height=\"${eff.height}\" />`;\n }\n }\n break;\n }\n case \"group\":\n // Groups are structural — no visual content in SVG either\n break;\n case \"ref\": {\n const refVisual = eff.visual as RefVisual;\n const refContent = renderRefSVG(eff, refVisual, doc, opts);\n content = refContent;\n break;\n }\n }\n\n if (layerDefs) allDefs.push(layerDefs);\n\n if (content) {\n const gOpen = gAttrs.length > 0 ? `<g ${gAttrs.join(\" \")}>` : \"<g>\";\n layerElements.push(`${pad}${gOpen}${content}</g>`);\n }\n }\n\n // Build SVG\n const lines: string[] = [];\n\n if (opts?.xmlDeclaration) {\n lines.push('<?xml version=\"1.0\" encoding=\"UTF-8\"?>');\n }\n\n const viewBox = opts?.viewBox !== false ? ` viewBox=\"0 0 ${width} ${height}\"` : \"\";\n const bg = doc.canvas.background;\n\n lines.push(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\"${viewBox}>`);\n\n // Defs section\n if (allDefs.length > 0) {\n lines.push(`${pad}<defs>`);\n for (const def of allDefs) {\n lines.push(`${pad}${pad}${def}`);\n }\n lines.push(`${pad}</defs>`);\n }\n\n // Background\n if (bg && bg !== \"transparent\") {\n lines.push(`${pad}<rect width=\"${width}\" height=\"${height}\" fill=\"${bg}\" />`);\n }\n\n // Layers\n lines.push(...layerElements);\n\n lines.push(\"</svg>\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render a ref layer as SVG. Uses documentResolver to inline sub-doc content,\n * or falls back to a dashed placeholder rectangle.\n */\nfunction renderRefSVG(\n eff: EffectiveLayer,\n visual: RefVisual,\n _parentDoc: AtelierDocument,\n opts?: RenderSVGOptions,\n _depth?: number,\n _visitedRefs?: Set<string>,\n): string {\n const resolver = opts?.documentResolver;\n\n if (!resolver) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" />`;\n }\n\n const depth = _depth ?? 0;\n const maxDepth = opts?.maxRefDepth ?? 4;\n if (depth >= maxDepth) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#c33\" stroke-dasharray=\"4 2\" /><text x=\"${eff.width / 2}\" y=\"${eff.height / 2}\" text-anchor=\"middle\" dominant-baseline=\"middle\" fill=\"#c33\" font-size=\"12\">MAX DEPTH</text>`;\n }\n\n const visitedRefs = _visitedRefs ?? new Set<string>();\n if (visitedRefs.has(visual.src)) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#c33\" stroke-dasharray=\"4 2\" /><text x=\"${eff.width / 2}\" y=\"${eff.height / 2}\" text-anchor=\"middle\" dominant-baseline=\"middle\" fill=\"#c33\" font-size=\"12\">CYCLE</text>`;\n }\n\n const subDoc = resolver(visual.src);\n if (!subDoc) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" /><text x=\"${eff.width / 2}\" y=\"${eff.height / 2}\" text-anchor=\"middle\" dominant-baseline=\"middle\" fill=\"#999\" font-size=\"12\">NOT FOUND</text>`;\n }\n\n const stateNames = Object.keys(subDoc.states);\n if (stateNames.length === 0) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" />`;\n }\n\n const stateName = visual.state ?? stateNames[0];\n const stateObj = subDoc.states[stateName];\n if (!stateObj) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" />`;\n }\n\n const maxFrame = Math.max(0, stateObj.duration - 1);\n const frame = Math.min(visual.frame ?? 0, maxFrame);\n\n visitedRefs.add(visual.src);\n\n // Render sub-doc as nested <svg> with viewBox for scaling\n const subW = subDoc.canvas.width;\n const subH = subDoc.canvas.height;\n const resolved = resolveFrame(subDoc, stateName, frame);\n\n const subParts: string[] = [];\n for (const rl of resolved.layers) {\n const subEff = buildEffectiveLayer(rl, subW, subH);\n if (!subEff.visible || subEff.opacity <= 0) continue;\n\n // Resolve asset\n if (rl.layer.visual.type === \"image\") {\n const iv = subEff.visual as ImageVisual;\n if (!iv.src && iv.assetId && subDoc.assets?.[iv.assetId]) {\n iv.src = subDoc.assets[iv.assetId].src;\n }\n }\n\n const transform = buildTransform(subEff);\n const styleAttrs = buildStyleAttrs(subEff);\n const gAttrs: string[] = [];\n if (transform) gAttrs.push(`transform=\"${transform}\"`);\n if (styleAttrs) gAttrs.push(styleAttrs);\n\n let childContent = \"\";\n switch (rl.layer.visual.type) {\n case \"shape\": {\n const result = renderShapeSVG(subEff, subEff.visual as import(\"@a-company/atelier-types\").ShapeVisual);\n childContent = result.elements;\n break;\n }\n case \"text\":\n childContent = renderTextSVG(subEff, subEff.visual as import(\"@a-company/atelier-types\").TextVisual);\n break;\n case \"image\": {\n const iv = subEff.visual as ImageVisual;\n if (iv.src) {\n childContent = `<image href=\"${escapeXml(iv.src)}\" width=\"${subEff.width}\" height=\"${subEff.height}\" />`;\n }\n break;\n }\n case \"ref\": {\n const refV = subEff.visual as RefVisual;\n childContent = renderRefSVG(subEff, refV, subDoc, opts, depth + 1, visitedRefs);\n break;\n }\n }\n\n if (childContent) {\n const gOpen = gAttrs.length > 0 ? `<g ${gAttrs.join(\" \")}>` : \"<g>\";\n subParts.push(`${gOpen}${childContent}</g>`);\n }\n }\n\n visitedRefs.delete(visual.src);\n\n return `<svg x=\"0\" y=\"0\" width=\"${eff.width}\" height=\"${eff.height}\" viewBox=\"0 0 ${subW} ${subH}\">${subParts.join(\"\")}</svg>`;\n}\n","import type { EffectiveLayer } from \"@a-company/atelier-canvas\";\n\n/** Build SVG transform attribute from effective layer values */\nexport function buildTransform(eff: EffectiveLayer): string {\n const parts: string[] = [];\n\n // Translate to position\n if (eff.x !== 0 || eff.y !== 0) {\n parts.push(`translate(${eff.x}, ${eff.y})`);\n }\n\n const totalRotation = eff.rotation + eff.motionPathAngle;\n if (totalRotation !== 0 || eff.scaleX !== 1 || eff.scaleY !== 1) {\n const ax = eff.anchorX * eff.width;\n const ay = eff.anchorY * eff.height;\n\n // Move to anchor, apply rotation/scale, move back\n if (ax !== 0 || ay !== 0) {\n parts.push(`translate(${ax}, ${ay})`);\n }\n if (totalRotation !== 0) {\n parts.push(`rotate(${totalRotation})`);\n }\n if (eff.scaleX !== 1 || eff.scaleY !== 1) {\n parts.push(`scale(${eff.scaleX}, ${eff.scaleY})`);\n }\n if (ax !== 0 || ay !== 0) {\n parts.push(`translate(${-ax}, ${-ay})`);\n }\n }\n\n return parts.length > 0 ? parts.join(\" \") : \"\";\n}\n\n/** Build common SVG style attributes */\nexport function buildStyleAttrs(eff: EffectiveLayer): string {\n const attrs: string[] = [];\n\n if (eff.opacity < 1) {\n attrs.push(`opacity=\"${eff.opacity}\"`);\n }\n\n if (eff.blendMode !== \"normal\") {\n attrs.push(`style=\"mix-blend-mode: ${eff.blendMode}\"`);\n }\n\n return attrs.join(\" \");\n}\n\n/** Escape XML special characters */\nexport function escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n","import type { Fill, LinearGradientFill, RadialGradientFill, Color, RGBAColor, HSLAColor } from \"@a-company/atelier-types\";\n\nlet gradientIdCounter = 0;\n\nexport function resetGradientCounter(): void {\n gradientIdCounter = 0;\n}\n\n/** Convert an Atelier Color to a CSS color string */\nexport function colorToCSS(color: Color): string {\n if (typeof color === \"string\") return color;\n if (\"r\" in color) {\n const c = color as RGBAColor;\n return `rgba(${Math.round(c.r)}, ${Math.round(c.g)}, ${Math.round(c.b)}, ${c.a})`;\n }\n if (\"h\" in color) {\n const c = color as HSLAColor;\n return `hsla(${c.h}, ${c.s}%, ${c.l}%, ${c.a})`;\n }\n return \"#000000\";\n}\n\n/** Generate SVG gradient defs and return the fill reference */\nexport function buildGradientDef(fill: Fill, width: number, height: number): { defs: string; fillRef: string } {\n if (fill.type === \"solid\") {\n return { defs: \"\", fillRef: colorToCSS(fill.color) };\n }\n\n if (fill.type === \"linear-gradient\") {\n return buildLinearGradient(fill, width, height);\n }\n\n if (fill.type === \"radial-gradient\") {\n return buildRadialGradient(fill, width, height);\n }\n\n return { defs: \"\", fillRef: \"none\" };\n}\n\nfunction buildLinearGradient(fill: LinearGradientFill, _width: number, _height: number): { defs: string; fillRef: string } {\n const id = `grad-${++gradientIdCounter}`;\n const rad = (fill.angle * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n\n // Map angle to x1,y1,x2,y2 (0-1 percentages)\n const x1 = 0.5 - cos * 0.5;\n const y1 = 0.5 - sin * 0.5;\n const x2 = 0.5 + cos * 0.5;\n const y2 = 0.5 + sin * 0.5;\n\n const stops = fill.stops.map(s =>\n `<stop offset=\"${s.offset}\" stop-color=\"${colorToCSS(s.color)}\" />`\n ).join(\"\");\n\n const def = `<linearGradient id=\"${id}\" x1=\"${x1}\" y1=\"${y1}\" x2=\"${x2}\" y2=\"${y2}\">${stops}</linearGradient>`;\n return { defs: def, fillRef: `url(#${id})` };\n}\n\nfunction buildRadialGradient(fill: RadialGradientFill, width: number, height: number): { defs: string; fillRef: string } {\n const id = `grad-${++gradientIdCounter}`;\n\n const cx = typeof fill.center.x === \"number\" ? fill.center.x : (parseFloat(fill.center.x) / 100) * width;\n const cy = typeof fill.center.y === \"number\" ? fill.center.y : (parseFloat(fill.center.y) / 100) * height;\n const r = typeof fill.radius === \"number\" ? fill.radius : (parseFloat(fill.radius) / 100) * Math.max(width, height);\n\n const stops = fill.stops.map(s =>\n `<stop offset=\"${s.offset}\" stop-color=\"${colorToCSS(s.color)}\" />`\n ).join(\"\");\n\n const def = `<radialGradient id=\"${id}\" cx=\"${cx}\" cy=\"${cy}\" r=\"${r}\" gradientUnits=\"userSpaceOnUse\">${stops}</radialGradient>`;\n return { defs: def, fillRef: `url(#${id})` };\n}\n","import type { ShapeVisual, Shape, RectShape, PathShape, Stroke } from \"@a-company/atelier-types\";\nimport type { EffectiveLayer } from \"@a-company/atelier-canvas\";\nimport { buildGradientDef, colorToCSS } from \"./svg-gradients.js\";\n\n/** Render a shape visual as SVG elements */\nexport function renderShapeSVG(\n eff: EffectiveLayer,\n visual: ShapeVisual,\n): { elements: string; defs: string } {\n const { shape } = visual;\n const defs: string[] = [];\n\n let fillAttr = \"none\";\n if (visual.fill) {\n const gradResult = buildGradientDef(visual.fill, eff.width, eff.height);\n if (gradResult.defs) defs.push(gradResult.defs);\n fillAttr = gradResult.fillRef;\n }\n\n let strokeAttrs = \"\";\n if (visual.stroke) {\n strokeAttrs = buildStrokeAttrs(visual.stroke);\n }\n\n const element = buildShapeElement(shape, eff.width, eff.height, fillAttr, strokeAttrs);\n return { elements: element, defs: defs.join(\"\") };\n}\n\nfunction buildShapeElement(\n shape: Shape,\n width: number,\n height: number,\n fill: string,\n strokeAttrs: string,\n): string {\n switch (shape.type) {\n case \"rect\":\n return buildRectElement(shape, width, height, fill, strokeAttrs);\n case \"ellipse\":\n return buildEllipseElement(width, height, fill, strokeAttrs);\n case \"path\":\n return buildPathElement(shape, fill, strokeAttrs);\n }\n}\n\nfunction buildRectElement(\n shape: RectShape,\n width: number,\n height: number,\n fill: string,\n strokeAttrs: string,\n): string {\n let rx = \"\";\n if (shape.cornerRadius) {\n const r = typeof shape.cornerRadius === \"number\" ? shape.cornerRadius : shape.cornerRadius[0];\n rx = ` rx=\"${r}\" ry=\"${r}\"`;\n }\n return `<rect width=\"${width}\" height=\"${height}\" fill=\"${fill}\"${rx}${strokeAttrs ? \" \" + strokeAttrs : \"\"} />`;\n}\n\nfunction buildEllipseElement(\n width: number,\n height: number,\n fill: string,\n strokeAttrs: string,\n): string {\n const cx = width / 2;\n const cy = height / 2;\n const rx = width / 2;\n const ry = height / 2;\n return `<ellipse cx=\"${cx}\" cy=\"${cy}\" rx=\"${rx}\" ry=\"${ry}\" fill=\"${fill}\"${strokeAttrs ? \" \" + strokeAttrs : \"\"} />`;\n}\n\nfunction buildPathElement(\n shape: PathShape,\n fill: string,\n strokeAttrs: string,\n): string {\n if (shape.points.length < 2) return \"\";\n\n const d: string[] = [];\n d.push(`M ${shape.points[0].x} ${shape.points[0].y}`);\n\n for (let i = 1; i < shape.points.length; i++) {\n const prev = shape.points[i - 1];\n const curr = shape.points[i];\n\n if (prev.out && curr.in) {\n d.push(`C ${prev.x + prev.out.x} ${prev.y + prev.out.y} ${curr.x + curr.in.x} ${curr.y + curr.in.y} ${curr.x} ${curr.y}`);\n } else {\n d.push(`L ${curr.x} ${curr.y}`);\n }\n }\n\n if (shape.closed) d.push(\"Z\");\n\n return `<path d=\"${d.join(\" \")}\" fill=\"${fill}\"${strokeAttrs ? \" \" + strokeAttrs : \"\"} />`;\n}\n\nfunction buildStrokeAttrs(stroke: Stroke): string {\n const parts: string[] = [];\n parts.push(`stroke=\"${colorToCSS(stroke.color)}\"`);\n parts.push(`stroke-width=\"${stroke.width}\"`);\n\n if (stroke.lineCap) parts.push(`stroke-linecap=\"${stroke.lineCap}\"`);\n if (stroke.lineJoin) parts.push(`stroke-linejoin=\"${stroke.lineJoin}\"`);\n if (stroke.dash) parts.push(`stroke-dasharray=\"${stroke.dash.join(\" \")}\"`);\n\n return parts.join(\" \");\n}\n","import type { TextVisual } from \"@a-company/atelier-types\";\nimport type { EffectiveLayer } from \"@a-company/atelier-canvas\";\nimport { colorToCSS } from \"./svg-gradients.js\";\nimport { escapeXml } from \"./svg-properties.js\";\n\n/** Render a text visual as SVG elements */\nexport function renderTextSVG(eff: EffectiveLayer, visual: TextVisual): string {\n const { style } = visual;\n\n const attrs: string[] = [];\n\n // Font attributes\n attrs.push(`font-family=\"${escapeXml(style.fontFamily)}\"`);\n attrs.push(`font-size=\"${style.fontSize}\"`);\n\n if (style.fontWeight && style.fontWeight !== \"normal\") {\n attrs.push(`font-weight=\"${style.fontWeight}\"`);\n }\n if (style.fontStyle && style.fontStyle !== \"normal\") {\n attrs.push(`font-style=\"${style.fontStyle}\"`);\n }\n\n // Color\n attrs.push(`fill=\"${colorToCSS(style.color)}\"`);\n\n // Text alignment\n const align = style.textAlign ?? \"left\";\n let textAnchor = \"start\";\n let x = 0;\n if (align === \"center\") {\n textAnchor = \"middle\";\n x = eff.width / 2;\n } else if (align === \"right\") {\n textAnchor = \"end\";\n x = eff.width;\n }\n attrs.push(`text-anchor=\"${textAnchor}\"`);\n\n // Letter spacing\n if (style.letterSpacing) {\n attrs.push(`letter-spacing=\"${style.letterSpacing}\"`);\n }\n\n // SVG text baseline: use dominant-baseline for top alignment\n attrs.push(`dominant-baseline=\"hanging\"`);\n\n return `<text x=\"${x}\" y=\"0\" ${attrs.join(\" \")}>${escapeXml(visual.content)}</text>`;\n}\n","import type { EffectiveLayer } from \"@a-company/atelier-canvas\";\n\nlet filterIdCounter = 0;\n\nexport function resetFilterCounter(): void {\n filterIdCounter = 0;\n}\n\n/** Build SVG filter definition for shadow effects */\nexport function buildShadowFilter(eff: EffectiveLayer): { defs: string; filterRef: string } | null {\n if (!eff.shadow) return null;\n\n const id = `filter-${++filterIdCounter}`;\n const { color, blur, offsetX, offsetY } = eff.shadow;\n\n const def = [\n `<filter id=\"${id}\" x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">`,\n `<feDropShadow dx=\"${offsetX}\" dy=\"${offsetY}\" stdDeviation=\"${blur / 2}\" flood-color=\"${color}\" />`,\n `</filter>`,\n ].join(\"\");\n\n return { defs: def, filterRef: `url(#${id})` };\n}\n\n/** Build SVG filter definition for tint effect (feFlood + feBlend multiply) */\nexport function buildTintFilter(eff: EffectiveLayer): { defs: string; filterRef: string } | null {\n if (!eff.tint || eff.tint.amount <= 0) return null;\n\n const id = `filter-${++filterIdCounter}`;\n const { color, amount } = eff.tint;\n\n const def = [\n `<filter id=\"${id}\" x=\"0%\" y=\"0%\" width=\"100%\" height=\"100%\">`,\n `<feFlood flood-color=\"${color}\" flood-opacity=\"${amount}\" result=\"tint\" />`,\n `<feBlend in=\"SourceGraphic\" in2=\"tint\" mode=\"multiply\" />`,\n `</filter>`,\n ].join(\"\");\n\n return { defs: def, filterRef: `url(#${id})` };\n}\n","import type { Shape } from \"@a-company/atelier-types\";\n\nlet clipIdCounter = 0;\n\nexport function resetClipCounter(): void {\n clipIdCounter = 0;\n}\n\n/** Build SVG clipPath definition */\nexport function buildClipPathDef(shape: Shape, width: number, height: number): { defs: string; clipRef: string } {\n const id = `clip-${++clipIdCounter}`;\n let pathContent = \"\";\n\n switch (shape.type) {\n case \"rect\":\n if (shape.cornerRadius) {\n const r = typeof shape.cornerRadius === \"number\" ? shape.cornerRadius : shape.cornerRadius[0];\n pathContent = `<rect width=\"${width}\" height=\"${height}\" rx=\"${r}\" ry=\"${r}\" />`;\n } else {\n pathContent = `<rect width=\"${width}\" height=\"${height}\" />`;\n }\n break;\n case \"ellipse\":\n pathContent = `<ellipse cx=\"${width / 2}\" cy=\"${height / 2}\" rx=\"${width / 2}\" ry=\"${height / 2}\" />`;\n break;\n case \"path\": {\n if (shape.points.length < 2) return { defs: \"\", clipRef: \"\" };\n const d: string[] = [];\n d.push(`M ${shape.points[0].x} ${shape.points[0].y}`);\n for (let i = 1; i < shape.points.length; i++) {\n const prev = shape.points[i - 1];\n const curr = shape.points[i];\n if (prev.out && curr.in) {\n d.push(`C ${prev.x + prev.out.x} ${prev.y + prev.out.y} ${curr.x + curr.in.x} ${curr.y + curr.in.y} ${curr.x} ${curr.y}`);\n } else {\n d.push(`L ${curr.x} ${curr.y}`);\n }\n }\n if (shape.closed) d.push(\"Z\");\n pathContent = `<path d=\"${d.join(\" \")}\" />`;\n break;\n }\n }\n\n const def = `<clipPath id=\"${id}\">${pathContent}</clipPath>`;\n return { defs: def, clipRef: `url(#${id})` };\n}\n","import type { Color, RGBAColor, HSLAColor } from \"@a-company/atelier-types\";\n\n/** Convert an Atelier color to Lottie [r, g, b, a] format (0–1 range) */\nexport function colorToLottie(color: Color): number[] {\n if (typeof color === \"string\") {\n return hexToLottie(color);\n }\n\n if (\"r\" in color) {\n const c = color as RGBAColor;\n return [c.r / 255, c.g / 255, c.b / 255, c.a];\n }\n\n if (\"h\" in color) {\n const c = color as HSLAColor;\n const rgb = hslToRgb(c.h, c.s, c.l);\n return [rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, c.a];\n }\n\n return [0, 0, 0, 1];\n}\n\nfunction hexToLottie(hex: string): number[] {\n const clean = hex.replace(\"#\", \"\");\n if (clean.length === 3 || clean.length === 4) {\n const r = parseInt(clean[0] + clean[0], 16) / 255;\n const g = parseInt(clean[1] + clean[1], 16) / 255;\n const b = parseInt(clean[2] + clean[2], 16) / 255;\n const a = clean.length === 4 ? parseInt(clean[3] + clean[3], 16) / 255 : 1;\n return [r, g, b, a];\n }\n const r = parseInt(clean.slice(0, 2), 16) / 255;\n const g = parseInt(clean.slice(2, 4), 16) / 255;\n const b = parseInt(clean.slice(4, 6), 16) / 255;\n const a = clean.length === 8 ? parseInt(clean.slice(6, 8), 16) / 255 : 1;\n return [r, g, b, a];\n}\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n s = s / 100;\n l = l / 100;\n const a = s * Math.min(l, 1 - l);\n const f = (n: number) => {\n const k = (n + h / 30) % 12;\n return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);\n };\n return [Math.round(f(0) * 255), Math.round(f(8) * 255), Math.round(f(4) * 255)];\n}\n","import type { ShapeVisual, Fill, Stroke } from \"@a-company/atelier-types\";\nimport type { LottieShapeItem } from \"./lottie-types.js\";\nimport { colorToLottie } from \"./map-colors.js\";\n\n/** Map an Atelier shape visual to Lottie shape items */\nexport function mapShapeVisual(\n visual: ShapeVisual,\n width: number,\n height: number,\n): LottieShapeItem[] {\n const items: LottieShapeItem[] = [];\n\n // Shape geometry\n switch (visual.shape.type) {\n case \"rect\":\n items.push({\n ty: \"rc\",\n nm: \"Rectangle\",\n d: 1,\n s: { a: 0, k: [width, height] },\n p: { a: 0, k: [width / 2, height / 2] },\n r: { a: 0, k: typeof visual.shape.cornerRadius === \"number\" ? visual.shape.cornerRadius : 0 },\n });\n break;\n case \"ellipse\":\n items.push({\n ty: \"el\",\n nm: \"Ellipse\",\n d: 1,\n s: { a: 0, k: [width, height] },\n p: { a: 0, k: [width / 2, height / 2] },\n });\n break;\n case \"path\": {\n const vertices = visual.shape.points.map(p => [p.x, p.y]);\n const inTangents = visual.shape.points.map(p => p.in ? [p.in.x, p.in.y] : [0, 0]);\n const outTangents = visual.shape.points.map(p => p.out ? [p.out.x, p.out.y] : [0, 0]);\n items.push({\n ty: \"sh\",\n nm: \"Path\",\n ks: {\n a: 0,\n k: {\n c: visual.shape.closed ?? false,\n v: vertices,\n i: inTangents,\n o: outTangents,\n },\n },\n });\n break;\n }\n }\n\n // Fill\n if (visual.fill) {\n items.push(mapFill(visual.fill, width, height));\n }\n\n // Stroke\n if (visual.stroke) {\n items.push(mapStroke(visual.stroke));\n }\n\n return items;\n}\n\nfunction mapFill(fill: Fill, _width: number, _height: number): LottieShapeItem {\n if (fill.type === \"solid\") {\n const color = colorToLottie(fill.color);\n return {\n ty: \"fl\",\n nm: \"Fill\",\n c: { a: 0, k: color.slice(0, 3) },\n o: { a: 0, k: (color[3] ?? 1) * 100 },\n r: 1,\n };\n }\n\n if (fill.type === \"linear-gradient\") {\n const stops: number[] = [];\n for (const stop of fill.stops) {\n const c = colorToLottie(stop.color);\n stops.push(stop.offset, c[0], c[1], c[2]);\n }\n return {\n ty: \"gf\",\n nm: \"Gradient Fill\",\n t: 1, // linear\n s: { a: 0, k: [0, 0] },\n e: { a: 0, k: [100, 0] },\n g: { p: fill.stops.length, k: { a: 0, k: stops } },\n r: 1,\n o: { a: 0, k: 100 },\n };\n }\n\n if (fill.type === \"radial-gradient\") {\n const stops: number[] = [];\n for (const stop of fill.stops) {\n const c = colorToLottie(stop.color);\n stops.push(stop.offset, c[0], c[1], c[2]);\n }\n return {\n ty: \"gf\",\n nm: \"Gradient Fill\",\n t: 2, // radial\n s: { a: 0, k: [50, 50] },\n e: { a: 0, k: [100, 50] },\n g: { p: fill.stops.length, k: { a: 0, k: stops } },\n r: 1,\n o: { a: 0, k: 100 },\n };\n }\n\n return { ty: \"fl\", nm: \"Fill\", c: { a: 0, k: [0, 0, 0] }, o: { a: 0, k: 100 }, r: 1 };\n}\n\nfunction mapStroke(stroke: Stroke): LottieShapeItem {\n const color = colorToLottie(stroke.color);\n return {\n ty: \"st\",\n nm: \"Stroke\",\n c: { a: 0, k: color.slice(0, 3) },\n o: { a: 0, k: (color[3] ?? 1) * 100 },\n w: { a: 0, k: stroke.width },\n lc: stroke.lineCap === \"round\" ? 2 : stroke.lineCap === \"square\" ? 3 : 1,\n lj: stroke.lineJoin === \"round\" ? 2 : stroke.lineJoin === \"bevel\" ? 3 : 1,\n };\n}\n","import type { Easing } from \"@a-company/atelier-types\";\n\nexport interface LottieEasing {\n i: { x: number[]; y: number[] };\n o: { x: number[]; y: number[] };\n}\n\n/** Map an Atelier easing to Lottie bezier easing curves */\nexport function mapEasing(easing: Easing | undefined): LottieEasing | { h: 1 } {\n if (!easing) return linearEasing();\n\n if (typeof easing === \"string\") {\n switch (easing) {\n case \"ease-in\":\n return bezierEasing(0.42, 0, 1, 1);\n case \"ease-out\":\n return bezierEasing(0, 0, 0.58, 1);\n case \"ease-in-out\":\n return bezierEasing(0.42, 0, 0.58, 1);\n default:\n return linearEasing();\n }\n }\n\n switch (easing.type) {\n case \"linear\":\n return linearEasing();\n case \"cubic-bezier\":\n return bezierEasing(easing.x1, easing.y1, easing.x2, easing.y2);\n case \"spring\":\n // Approximate spring as a cubic-bezier (lossy)\n return bezierEasing(0.25, 0.1, 0.25, 1);\n case \"step\":\n // Steps map to hold keyframes\n return { h: 1 };\n default:\n return linearEasing();\n }\n}\n\nfunction linearEasing(): LottieEasing {\n return {\n i: { x: [0.833], y: [0.833] },\n o: { x: [0.167], y: [0.167] },\n };\n}\n\nfunction bezierEasing(x1: number, y1: number, x2: number, y2: number): LottieEasing {\n return {\n i: { x: [x2], y: [y2] },\n o: { x: [x1], y: [y1] },\n };\n}\n\n/** Check if an easing is lossy (spring/step → approximated) */\nexport function isLossyEasing(easing: Easing | undefined): string | null {\n if (!easing || typeof easing === \"string\") return null;\n if (easing.type === \"spring\") return \"Spring easing approximated as cubic-bezier\";\n if (easing.type === \"step\") return \"Step easing mapped to hold keyframes\";\n return null;\n}\n","import type { Delta, AnimatableProperty } from \"@a-company/atelier-types\";\nimport type { LottieAnimatedValue, LottieAnimatedMultiValue, LottieKeyframe, LottieMultiKeyframe } from \"./lottie-types.js\";\nimport { mapEasing, isLossyEasing } from \"./map-easing.js\";\n\n/** Map deltas for a single layer+property to Lottie animated value */\nexport function mapDeltasToAnimated(\n deltas: Delta[],\n property: AnimatableProperty,\n warnings: string[],\n): LottieAnimatedValue {\n if (deltas.length === 0) {\n return { a: 0, k: 0 };\n }\n\n // Check for lossy easings\n for (const d of deltas) {\n const lossyMsg = isLossyEasing(d.easing);\n if (lossyMsg) warnings.push(`${property}: ${lossyMsg}`);\n }\n\n // If expressions, warn and use static\n for (const d of deltas) {\n if (isExpression(d.from) || isExpression(d.to)) {\n warnings.push(`${property}: Expression values not supported in Lottie, using static values`);\n return { a: 0, k: typeof d.from === \"number\" ? d.from : 0 };\n }\n }\n\n // Single delta — simple animated value\n if (deltas.length === 1) {\n const d = deltas[0];\n const fromVal = resolveValue(d.from, property);\n const toVal = resolveValue(d.to, property);\n\n if (fromVal === toVal) {\n return { a: 0, k: fromVal };\n }\n\n const easing = mapEasing(d.easing);\n const kfs: LottieKeyframe[] = [];\n\n if (\"h\" in easing) {\n kfs.push({ t: d.range[0], s: [fromVal], h: 1 });\n kfs.push({ t: d.range[1], s: [toVal] });\n } else {\n kfs.push({ t: d.range[0], s: [fromVal], e: [toVal], i: easing.i, o: easing.o });\n kfs.push({ t: d.range[1], s: [toVal] });\n }\n\n return { a: 1, k: kfs };\n }\n\n // Multiple deltas — chain keyframes\n const sorted = [...deltas].sort((a, b) => a.range[0] - b.range[0]);\n const kfs: LottieKeyframe[] = [];\n\n for (const d of sorted) {\n const fromVal = resolveValue(d.from, property);\n const toVal = resolveValue(d.to, property);\n const easing = mapEasing(d.easing);\n\n if (\"h\" in easing) {\n kfs.push({ t: d.range[0], s: [fromVal], h: 1 });\n } else {\n kfs.push({ t: d.range[0], s: [fromVal], e: [toVal], i: easing.i, o: easing.o });\n }\n }\n\n // Final keyframe\n const last = sorted[sorted.length - 1];\n kfs.push({ t: last.range[1], s: [resolveValue(last.to, property)] });\n\n return { a: 1, k: kfs };\n}\n\n/** Map position deltas (frame.x, frame.y) to Lottie multi-dimensional animated value */\nexport function mapPositionDeltas(\n xDeltas: Delta[],\n yDeltas: Delta[],\n baseX: number,\n baseY: number,\n warnings: string[],\n): LottieAnimatedMultiValue {\n const hasXAnim = xDeltas.length > 0;\n const hasYAnim = yDeltas.length > 0;\n\n if (!hasXAnim && !hasYAnim) {\n return { a: 0, k: [baseX, baseY, 0] };\n }\n\n // Collect all unique frame points\n const frames = new Set<number>();\n for (const d of [...xDeltas, ...yDeltas]) {\n frames.add(d.range[0]);\n frames.add(d.range[1]);\n }\n const sortedFrames = [...frames].sort((a, b) => a - b);\n\n if (sortedFrames.length < 2) {\n return { a: 0, k: [baseX, baseY, 0] };\n }\n\n // Build multi-dimensional keyframes\n const kfs: LottieMultiKeyframe[] = [];\n for (let i = 0; i < sortedFrames.length; i++) {\n const f = sortedFrames[i];\n const x = resolveAtFrame(xDeltas, f, baseX);\n const y = resolveAtFrame(yDeltas, f, baseY);\n\n if (i < sortedFrames.length - 1) {\n const nextF = sortedFrames[i + 1];\n const nextX = resolveAtFrame(xDeltas, nextF, baseX);\n const nextY = resolveAtFrame(yDeltas, nextF, baseY);\n\n // Find the active delta's easing\n const activeX = xDeltas.find(d => d.range[0] <= f && d.range[1] >= f);\n const activeY = yDeltas.find(d => d.range[0] <= f && d.range[1] >= f);\n const easing = mapEasing(activeX?.easing ?? activeY?.easing);\n\n if (\"h\" in easing) {\n kfs.push({ t: f, s: [x, y, 0], h: 1 });\n } else {\n kfs.push({ t: f, s: [x, y, 0], e: [nextX, nextY, 0], i: easing.i, o: easing.o });\n }\n } else {\n kfs.push({ t: f, s: [x, y, 0] });\n }\n }\n\n // Check for lossy warnings\n for (const d of [...xDeltas, ...yDeltas]) {\n const msg = isLossyEasing(d.easing);\n if (msg) warnings.push(`position: ${msg}`);\n }\n\n return { a: 1, k: kfs };\n}\n\nfunction resolveAtFrame(deltas: Delta[], frame: number, base: number): number {\n for (const d of deltas) {\n if (frame >= d.range[0] && frame <= d.range[1]) {\n const from = typeof d.from === \"number\" ? d.from : base;\n const to = typeof d.to === \"number\" ? d.to : base;\n const progress = d.range[0] === d.range[1] ? 1 : (frame - d.range[0]) / (d.range[1] - d.range[0]);\n return from + (to - from) * progress;\n }\n }\n // Hold last completed value\n let lastCompleted: Delta | undefined;\n for (const d of deltas) {\n if (frame > d.range[1]) {\n if (!lastCompleted || d.range[1] > lastCompleted.range[1]) {\n lastCompleted = d;\n }\n }\n }\n if (lastCompleted) return typeof lastCompleted.to === \"number\" ? lastCompleted.to : base;\n return base;\n}\n\nfunction resolveValue(val: unknown, _property: AnimatableProperty): number {\n if (typeof val === \"number\") return val;\n if (typeof val === \"string\" && val.startsWith(\"#\")) {\n // Color — for Lottie, colors are handled separately\n return 0;\n }\n return 0;\n}\n\nfunction isExpression(val: unknown): boolean {\n return typeof val === \"object\" && val !== null && \"expr\" in val;\n}\n","import type { AtelierDocument, Layer, Delta, State, UnitValue } from \"@a-company/atelier-types\";\nimport type { LottieLayer, LottieTransform, LottieTextData } from \"./lottie-types.js\";\nimport { mapShapeVisual } from \"./map-shapes.js\";\nimport { mapDeltasToAnimated, mapPositionDeltas } from \"./map-keyframes.js\";\nimport { colorToLottie } from \"./map-colors.js\";\n\n/** Resolve a UnitValue to a plain number (percentages treated as 0 for Lottie) */\nfunction toNum(v: UnitValue): number {\n return typeof v === \"number\" ? v : 0;\n}\n\n/** Map all layers in a document+state to Lottie layers */\nexport function mapLayers(\n doc: AtelierDocument,\n state: State,\n warnings: string[],\n): LottieLayer[] {\n const layerIndexMap = new Map<string, number>();\n doc.layers.forEach((l, i) => layerIndexMap.set(l.id, i));\n\n return doc.layers.map((layer, index) => {\n const deltas = state.deltas.filter(d => d.layer === layer.id);\n return mapLayer(layer, index, deltas, layerIndexMap, doc, warnings);\n });\n}\n\nfunction mapLayer(\n layer: Layer,\n index: number,\n deltas: Delta[],\n layerIndexMap: Map<string, number>,\n doc: AtelierDocument,\n warnings: string[],\n): LottieLayer {\n const duration = getMaxFrame(deltas, doc);\n\n const base: LottieLayer = {\n ty: getLayerType(layer),\n nm: layer.id,\n ind: index,\n ip: 0,\n op: duration,\n st: 0,\n ks: buildTransform(layer, deltas, warnings),\n };\n\n // Parent\n if (layer.parentId) {\n const parentIdx = layerIndexMap.get(layer.parentId);\n if (parentIdx !== undefined) {\n base.parent = parentIdx;\n }\n }\n\n // Blend mode\n if (layer.blendMode) {\n base.bm = mapBlendMode(layer.blendMode);\n }\n\n // Shape layer\n if (layer.visual.type === \"shape\") {\n base.shapes = mapShapeVisual(layer.visual, toNum(layer.bounds.width), toNum(layer.bounds.height));\n }\n\n // Text layer\n if (layer.visual.type === \"text\") {\n const color = colorToLottie(layer.visual.style.color);\n base.t = {\n d: {\n k: [{\n s: {\n s: layer.visual.style.fontSize,\n f: layer.visual.style.fontFamily,\n t: layer.visual.content,\n fc: color.slice(0, 3),\n j: layer.visual.style.textAlign === \"center\" ? 1 :\n layer.visual.style.textAlign === \"right\" ? 2 : 0,\n },\n t: 0,\n }],\n },\n } as LottieTextData;\n }\n\n // Image layer\n if (layer.visual.type === \"image\") {\n base.refId = layer.visual.assetId;\n base.w = toNum(layer.bounds.width);\n base.h = toNum(layer.bounds.height);\n\n if (layer.visual.spritesheet) {\n warnings.push(`Layer \"${layer.id}\": Spritesheet animation not supported in Lottie export`);\n }\n if (layer.visual.sourceRect) {\n warnings.push(`Layer \"${layer.id}\": sourceRect cropping not supported in Lottie export`);\n }\n }\n\n // Tint warning\n if (layer.tint && layer.tint.amount > 0) {\n warnings.push(`Layer \"${layer.id}\": Tint effect not supported in Lottie export`);\n }\n\n return base;\n}\n\nfunction getLayerType(layer: Layer): number {\n switch (layer.visual.type) {\n case \"shape\": return 4;\n case \"text\": return 5;\n case \"image\": return 2;\n case \"group\": return 3; // null layer\n case \"ref\": return 0; // precomp\n default: return 4;\n }\n}\n\nfunction buildTransform(\n layer: Layer,\n deltas: Delta[],\n warnings: string[],\n): LottieTransform {\n // Group deltas by property\n const byProp = new Map<string, Delta[]>();\n for (const d of deltas) {\n if (!byProp.has(d.property)) byProp.set(d.property, []);\n byProp.get(d.property)!.push(d);\n }\n\n const xDeltas = byProp.get(\"frame.x\") ?? [];\n const yDeltas = byProp.get(\"frame.y\") ?? [];\n const opacityDeltas = byProp.get(\"opacity\") ?? [];\n const rotationDeltas = byProp.get(\"rotation\") ?? [];\n const scaleXDeltas = byProp.get(\"scale.x\") ?? [];\n const scaleYDeltas = byProp.get(\"scale.y\") ?? [];\n\n // Position\n const position = mapPositionDeltas(\n xDeltas, yDeltas,\n typeof layer.frame.x === \"number\" ? layer.frame.x : 0,\n typeof layer.frame.y === \"number\" ? layer.frame.y : 0,\n warnings,\n );\n\n // Opacity (Lottie uses 0–100)\n let opacity;\n if (opacityDeltas.length > 0) {\n const raw = mapDeltasToAnimated(opacityDeltas, \"opacity\", warnings);\n // Scale 0-1 to 0-100\n if (raw.a === 0) {\n opacity = { a: 0 as const, k: (raw.k as number) * 100 };\n } else {\n const kfs = (raw.k as Array<{ t: number; s: [number]; e?: [number]; [key: string]: unknown }>).map(kf => ({\n ...kf,\n s: [kf.s[0] * 100] as [number],\n e: kf.e ? [kf.e[0] * 100] as [number] : undefined,\n }));\n opacity = { a: 1 as const, k: kfs };\n }\n } else {\n opacity = { a: 0 as const, k: (layer.opacity ?? 1) * 100 };\n }\n\n // Rotation\n const rotation = rotationDeltas.length > 0\n ? mapDeltasToAnimated(rotationDeltas, \"rotation\", warnings)\n : { a: 0 as const, k: layer.rotation ?? 0 };\n\n // Scale (Lottie uses 0–100)\n const baseScaleX = (layer.scale?.x ?? 1) * 100;\n const baseScaleY = (layer.scale?.y ?? 1) * 100;\n let scale;\n if (scaleXDeltas.length > 0 || scaleYDeltas.length > 0) {\n // Simplified: use x deltas for now\n scale = { a: 0 as const, k: [baseScaleX, baseScaleY, 100] };\n if (scaleXDeltas.length > 0 || scaleYDeltas.length > 0) {\n warnings.push(\"Scale animation partially mapped to Lottie\");\n }\n } else {\n scale = { a: 0 as const, k: [baseScaleX, baseScaleY, 100] };\n }\n\n // Anchor point\n const ax = (layer.anchorPoint?.x ?? 0) * toNum(layer.bounds.width);\n const ay = (layer.anchorPoint?.y ?? 0) * toNum(layer.bounds.height);\n\n return {\n o: opacity,\n r: rotation,\n p: position,\n a: { a: 0, k: [ax, ay, 0] },\n s: scale,\n };\n}\n\nfunction getMaxFrame(deltas: Delta[], doc: AtelierDocument): number {\n let max = 0;\n for (const state of Object.values(doc.states)) {\n if (state.duration > max) max = state.duration;\n }\n for (const d of deltas) {\n if (d.range[1] > max) max = d.range[1];\n }\n return max || 60;\n}\n\nfunction mapBlendMode(mode: string): number {\n const map: Record<string, number> = {\n normal: 0, multiply: 1, screen: 2, overlay: 3,\n darken: 4, lighten: 5, \"color-dodge\": 6, \"color-burn\": 7,\n \"hard-light\": 8, \"soft-light\": 9, difference: 10, exclusion: 11,\n hue: 12, saturation: 13, color: 14, luminosity: 15,\n };\n return map[mode] ?? 0;\n}\n","import type { AtelierDocument, State } from \"@a-company/atelier-types\";\n\n/** Check for unsupported features and collect warnings */\nexport function collectUnsupportedWarnings(doc: AtelierDocument, state: State): string[] {\n const warnings: string[] = [];\n\n // Audio layers not supported in Lottie (v1.0: audio is layer-scoped, not state-scoped)\n const audioLayers = doc.layers.filter((l) => l.visual.type === \"audio\");\n if (audioLayers.length > 0) {\n warnings.push(\n `${audioLayers.length} audio layer(s) are not supported in Lottie format and will be dropped`,\n );\n }\n\n // Expressions not supported\n for (const delta of state.deltas) {\n if (isExpression(delta.from) || isExpression(delta.to)) {\n warnings.push(`Expression values on \"${delta.layer}.${delta.property}\" not supported in Lottie`);\n }\n }\n\n // Shadow not supported in base Lottie\n for (const layer of doc.layers) {\n if (layer.shadow) {\n warnings.push(`Shadow on layer \"${layer.id}\" is not supported in base Lottie format`);\n }\n }\n\n // Motion path not directly mapped\n for (const layer of doc.layers) {\n if (layer.motionPath) {\n warnings.push(`Motion path on layer \"${layer.id}\" is not directly mappable to Lottie`);\n }\n }\n\n // Clip paths have limited support\n for (const layer of doc.layers) {\n if (layer.clipPath) {\n warnings.push(`Clip path on layer \"${layer.id}\" mapped as Lottie mask (partial support)`);\n }\n }\n\n // States/transitions\n if (Object.keys(doc.states).length > 1) {\n warnings.push(\"Multiple states flattened to single timeline in Lottie export\");\n }\n\n return warnings;\n}\n\nfunction isExpression(val: unknown): boolean {\n return typeof val === \"object\" && val !== null && \"expr\" in val;\n}\n","import type { AtelierDocument } from \"@a-company/atelier-types\";\nimport type { LottieAnimation, LottieAsset } from \"./lottie-types.js\";\nimport { mapLayers } from \"./map-layers.js\";\nimport { collectUnsupportedWarnings } from \"./warnings.js\";\n\nexport interface ExportLottieOptions {\n /** State to export (defaults to first state) */\n state?: string;\n}\n\nexport interface ExportLottieResult {\n /** The Lottie JSON animation */\n json: LottieAnimation;\n /** Warnings about unsupported features */\n warnings: string[];\n}\n\n/**\n * Export an Atelier document to Lottie JSON format.\n * This is a lossy conversion — not all features are supported.\n */\nexport function exportToLottie(\n doc: AtelierDocument,\n opts?: ExportLottieOptions,\n): ExportLottieResult {\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) {\n throw new Error(\"Document has no states to export\");\n }\n\n const stateName = opts?.state ?? stateNames[0];\n const state = doc.states[stateName];\n if (!state) {\n throw new Error(`State \"${stateName}\" not found`);\n }\n\n const warnings: string[] = [];\n\n // Collect unsupported feature warnings\n warnings.push(...collectUnsupportedWarnings(doc, state));\n\n // Map layers\n const layers = mapLayers(doc, state, warnings);\n\n // Map assets\n const assets: LottieAsset[] = [];\n if (doc.assets) {\n for (const [id, asset] of Object.entries(doc.assets)) {\n if (asset.type === \"image\") {\n assets.push({\n id,\n w: 100,\n h: 100,\n p: asset.src,\n e: 0,\n });\n }\n }\n }\n\n const json: LottieAnimation = {\n v: \"5.7.4\",\n fr: doc.canvas.fps,\n ip: 0,\n op: state.duration,\n w: doc.canvas.width,\n h: doc.canvas.height,\n nm: doc.name,\n layers,\n ...(assets.length > 0 ? { assets } : {}),\n };\n\n // Deduplicate warnings\n const uniqueWarnings = [...new Set(warnings)];\n\n return { json, warnings: uniqueWarnings };\n}\n","// @a-company/atelier-mcp — Asset management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, ImageVisual, VideoVisual, AudioVisual } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_asset ─────────────────────────────────────────\n server.tool(\n \"atelier_add_asset\",\n \"Register an external asset (image, SVG, font, animation, audio) on a document\",\n {\n id: z.string().describe(\"Document ID\"),\n assetId: z.string().describe(\"Unique asset identifier\"),\n type: z.enum([\"image\", \"svg\", \"font\", \"animation\", \"audio\"]).describe(\"Asset type\"),\n src: z.string().describe(\"File path or URL\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n spritesheet: z.object({\n columns: z.number().int().positive().describe(\"Number of columns in the spritesheet grid\"),\n rows: z.number().int().positive().describe(\"Number of rows in the spritesheet grid\"),\n frameCount: z.number().int().positive().optional().describe(\"Total frame count (defaults to columns × rows)\"),\n frameWidth: z.number().positive().describe(\"Width of each frame in pixels\"),\n frameHeight: z.number().positive().describe(\"Height of each frame in pixels\"),\n }).optional().describe(\"Spritesheet metadata (image assets only)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, assetId, type, src, description, spritesheet }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.assets) doc.assets = {};\n if (doc.assets[assetId]) return err(`Asset \"${assetId}\" already exists`);\n\n doc.assets[assetId] = {\n type,\n src,\n ...(description !== undefined ? { description } : {}),\n ...(spritesheet ? { spritesheet } : {}),\n };\n return ok({ assetId, type, src });\n },\n );\n\n // ── atelier_list_assets ───────────────────────────────────────\n server.tool(\n \"atelier_list_assets\",\n \"List all registered assets with usage info (which layers/states reference them)\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const assets = doc.assets ?? {};\n const entries = Object.entries(assets).map(([assetId, asset]) => {\n // Find layers referencing this asset (ImageVisual, VideoVisual, AudioVisual all\n // address assets by `assetId`). v1.0: audio is layer-scoped — there's no\n // longer a per-state audio reference to track here.\n const referencingLayers = doc.layers\n .filter(l => {\n const v = l.visual as ImageVisual | VideoVisual | AudioVisual | { type: string; assetId?: string };\n return (\n (v.type === \"image\" || v.type === \"video\" || v.type === \"audio\") &&\n \"assetId\" in v && v.assetId === assetId\n );\n })\n .map(l => l.id);\n\n return {\n assetId,\n type: asset.type,\n src: asset.src,\n description: asset.description,\n usedByLayers: referencingLayers,\n };\n });\n\n return ok({ count: entries.length, assets: entries });\n },\n );\n\n // ── atelier_remove_asset ──────────────────────────────────────\n server.tool(\n \"atelier_remove_asset\",\n \"Remove a registered asset. Warns if layers still reference it.\",\n {\n id: z.string().describe(\"Document ID\"),\n assetId: z.string().describe(\"Asset ID to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, assetId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.assets?.[assetId]) return err(`Asset \"${assetId}\" not found`);\n\n const warnings: string[] = [];\n\n // Check layers (image/video/audio) referencing this asset\n const referencingLayers = doc.layers\n .filter(l => {\n const v = l.visual as ImageVisual | VideoVisual | AudioVisual | { type: string; assetId?: string };\n return (\n (v.type === \"image\" || v.type === \"video\" || v.type === \"audio\") &&\n \"assetId\" in v && v.assetId === assetId\n );\n })\n .map(l => l.id);\n if (referencingLayers.length > 0) {\n warnings.push(`Asset is referenced by layer(s): ${referencingLayers.join(\", \")}`);\n }\n\n delete doc.assets[assetId];\n return ok({ assetId, warnings });\n },\n );\n}\n","// @a-company/atelier-mcp — Variable management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { findTemplateVariables } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_variable ──────────────────────────────────────\n server.tool(\n \"atelier_add_variable\",\n \"Define a template variable on a document\",\n {\n id: z.string().describe(\"Document ID\"),\n variableName: z.string().describe(\"Variable name (used in {{variableName}} patterns)\"),\n type: z.enum([\"string\", \"number\", \"color\", \"asset\", \"boolean\"]).describe(\"Variable type\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n default: z.unknown().optional().describe(\"Default value\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async (args) => {\n const result = getDoc(store, args.id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.variables) doc.variables = {};\n if (doc.variables[args.variableName]) return err(`Variable \"${args.variableName}\" already exists`);\n\n doc.variables[args.variableName] = {\n type: args.type,\n ...(args.description !== undefined ? { description: args.description } : {}),\n ...(args.default !== undefined ? { default: args.default } : {}),\n };\n return ok({ variableName: args.variableName, type: args.type });\n },\n );\n\n // ── atelier_list_variables ────────────────────────────────────\n server.tool(\n \"atelier_list_variables\",\n \"List all declared variables with usage info (which {{references}} exist in the document)\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const variables = doc.variables ?? {};\n const referenced = findTemplateVariables(doc);\n\n const entries = Object.entries(variables).map(([name, variable]) => ({\n name,\n type: variable.type,\n description: variable.description,\n default: variable.default,\n referenced: referenced.includes(name),\n }));\n\n const undeclared = referenced.filter(r => !variables[r]);\n\n return ok({ count: entries.length, variables: entries, undeclared });\n },\n );\n\n // ── atelier_remove_variable ───────────────────────────────────\n server.tool(\n \"atelier_remove_variable\",\n \"Remove a declared variable. Warns if {{references}} still exist in the document.\",\n {\n id: z.string().describe(\"Document ID\"),\n variableName: z.string().describe(\"Variable name to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, variableName }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.variables?.[variableName]) return err(`Variable \"${variableName}\" not found`);\n\n const warnings: string[] = [];\n const referenced = findTemplateVariables(doc);\n if (referenced.includes(variableName)) {\n warnings.push(`Variable \"{{${variableName}}}\" is still referenced in the document`);\n }\n\n delete doc.variables[variableName];\n if (Object.keys(doc.variables).length === 0) {\n doc.variables = undefined;\n }\n return ok({ variableName, warnings });\n },\n );\n}\n","// @a-company/atelier-mcp — Interaction management tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Interaction } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_interaction ───────────────────────────────────\n server.tool(\n \"atelier_add_interaction\",\n \"Add a trigger-action interaction to a layer (click, hover, timer, signal → go-to-state, emit-signal, set-variable, toggle-visibility)\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer to attach the interaction to\"),\n interactionId: z.string().describe(\"Unique interaction ID\"),\n trigger: z.object({\n type: z.enum([\"click\", \"hover\", \"pointerdown\", \"pointerup\", \"timer\", \"signal\"]).describe(\"Trigger type\"),\n delay: z.number().optional().describe(\"Delay in ms (timer trigger only)\"),\n signal: z.string().optional().describe(\"Signal name (signal trigger only)\"),\n }).describe(\"What triggers the interaction\"),\n action: z.object({\n type: z.enum([\"go-to-state\", \"emit-signal\", \"set-variable\", \"toggle-visibility\"]).describe(\"Action type\"),\n state: z.string().optional().describe(\"Target state (go-to-state only)\"),\n signal: z.string().optional().describe(\"Signal to emit (emit-signal only)\"),\n variable: z.string().optional().describe(\"Variable name (set-variable only)\"),\n value: z.unknown().optional().describe(\"Value to set (set-variable only)\"),\n targetLayer: z.string().optional().describe(\"Target layer ID (toggle-visibility, defaults to self)\"),\n }).describe(\"What happens when triggered\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, interactionId, trigger, action, description }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (!layer.interactions) layer.interactions = [];\n if (layer.interactions.some(i => i.id === interactionId)) {\n return err(`Interaction \"${interactionId}\" already exists on layer \"${layerId}\"`);\n }\n\n // Validate trigger-specific fields\n if (trigger.type === \"timer\" && trigger.delay === undefined) {\n return err(\"Timer trigger requires a delay\");\n }\n if (trigger.type === \"signal\" && !trigger.signal) {\n return err(\"Signal trigger requires a signal name\");\n }\n\n // Validate action-specific fields\n if (action.type === \"go-to-state\") {\n if (!action.state) return err(\"go-to-state action requires a state name\");\n if (!doc.states[action.state]) return err(`Target state \"${action.state}\" not found`);\n }\n if (action.type === \"emit-signal\" && !action.signal) {\n return err(\"emit-signal action requires a signal name\");\n }\n if (action.type === \"set-variable\") {\n if (!action.variable) return err(\"set-variable action requires a variable name\");\n if (action.value === undefined) return err(\"set-variable action requires a value\");\n }\n if (action.type === \"toggle-visibility\" && action.targetLayer) {\n if (!doc.layers.find(l => l.id === action.targetLayer)) {\n return err(`Target layer \"${action.targetLayer}\" not found`);\n }\n }\n\n const interaction: Interaction = {\n id: interactionId,\n trigger: trigger as Interaction[\"trigger\"],\n action: action as Interaction[\"action\"],\n ...(description !== undefined ? { description } : {}),\n };\n\n layer.interactions.push(interaction);\n return ok({ layerId, interactionId, triggerType: trigger.type, actionType: action.type });\n },\n );\n\n // ── atelier_list_interactions ─────────────────────────────────\n server.tool(\n \"atelier_list_interactions\",\n \"List all interactions across all layers or for a specific layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().optional().describe(\"Optional: filter to a specific layer\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, layerId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layers = layerId\n ? doc.layers.filter(l => l.id === layerId)\n : doc.layers;\n\n if (layerId && layers.length === 0) return err(`Layer \"${layerId}\" not found`);\n\n const interactions = layers.flatMap(l =>\n (l.interactions ?? []).map(i => ({\n layerId: l.id,\n interactionId: i.id,\n triggerType: i.trigger.type,\n actionType: i.action.type,\n description: i.description,\n trigger: i.trigger,\n action: i.action,\n })),\n );\n\n return ok({ count: interactions.length, interactions });\n },\n );\n\n // ── atelier_remove_interaction ────────────────────────────────\n server.tool(\n \"atelier_remove_interaction\",\n \"Remove an interaction from a layer\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID\"),\n interactionId: z.string().describe(\"Interaction ID to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ id, layerId, interactionId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n\n if (!layer.interactions) return err(`Interaction \"${interactionId}\" not found on layer \"${layerId}\"`);\n\n const idx = layer.interactions.findIndex(i => i.id === interactionId);\n if (idx === -1) return err(`Interaction \"${interactionId}\" not found on layer \"${layerId}\"`);\n\n layer.interactions.splice(idx, 1);\n if (layer.interactions.length === 0) {\n layer.interactions = undefined;\n }\n return ok({ layerId, interactionId, remainingInteractions: layer.interactions?.length ?? 0 });\n },\n );\n}\n","// @a-company/atelier-mcp — Ref layer (composition/nesting) tools\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, RefVisual } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_set_ref ───────────────────────────────────────────\n server.tool(\n \"atelier_set_ref\",\n \"Set the source reference on a ref-type layer. Can point to a file path or another in-memory document ID.\",\n {\n id: z.string().describe(\"Document ID\"),\n layerId: z.string().describe(\"Layer ID (must be a ref visual)\"),\n src: z.string().describe(\"File path, URL, or in-memory document ID\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, layerId, src }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layer = doc.layers.find(l => l.id === layerId);\n if (!layer) return err(`Layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"ref\") return err(`Layer \"${layerId}\" is type \"${layer.visual.type}\", not \"ref\"`);\n\n // Prevent self-reference\n if (src === id) return err(\"Cannot reference self — would cause infinite recursion\");\n\n (layer.visual as RefVisual).src = src;\n\n // Check if src is an in-memory document\n const isInMemory = store.has(src);\n return ok({ layerId, src, resolvedInMemory: isInMemory });\n },\n );\n\n // ── atelier_resolve_refs ──────────────────────────────────────\n server.tool(\n \"atelier_resolve_refs\",\n \"Check which ref layers can be resolved (point to valid in-memory documents)\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const refs = doc.layers\n .filter(l => l.visual.type === \"ref\")\n .map(l => {\n const src = (l.visual as RefVisual).src;\n const resolved = store.has(src);\n const targetDoc = resolved ? store.get(src) : undefined;\n return {\n layerId: l.id,\n src,\n resolved,\n targetName: targetDoc?.name,\n targetLayerCount: targetDoc?.layers.length,\n targetStateCount: targetDoc ? Object.keys(targetDoc.states).length : undefined,\n };\n });\n\n const resolvedCount = refs.filter(r => r.resolved).length;\n return ok({ count: refs.length, resolvedCount, refs });\n },\n );\n}\n","// @a-company/atelier-mcp — Performance tools (profiling, frame diff, batch preview)\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { resolveFrame } from \"@a-company/atelier-core\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_profile ─────────────────────────────────────────\n server.tool(\n \"atelier_profile\",\n \"Profile frame resolution performance — returns timing, layer count, property count, and delta count for a frame\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to profile\"),\n frame: z.number().int().min(0).describe(\"Frame number to resolve\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frame }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) {\n return err(`State \"${stateName}\" not found`);\n }\n\n const state = doc.states[stateName];\n const deltaCount = state.deltas.length;\n const expressionCount = state.deltas.filter(\n d => (typeof d.from === \"object\" && d.from !== null && \"expr\" in d.from) ||\n (typeof d.to === \"object\" && d.to !== null && \"expr\" in d.to)\n ).length;\n\n const start = performance.now();\n const resolved = resolveFrame(doc, stateName, frame);\n const resolveTimeMs = performance.now() - start;\n\n let propertiesComputed = 0;\n const layerDetails = resolved.layers.map(rl => {\n const propCount = Object.keys(rl.computedProperties).length;\n propertiesComputed += propCount;\n return {\n id: rl.id,\n visualType: rl.layer.visual.type,\n propertiesComputed: propCount,\n properties: Object.keys(rl.computedProperties),\n };\n });\n\n return ok({\n stateName,\n frame,\n duration: state.duration,\n resolveTimeMs: Math.round(resolveTimeMs * 1000) / 1000,\n layerCount: doc.layers.length,\n deltaCount,\n expressionCount,\n propertiesComputed,\n layerDetails,\n });\n },\n );\n\n // ── atelier_diff_frames ────────────────────────────────────\n server.tool(\n \"atelier_diff_frames\",\n \"Compare two frames and return only the properties that changed between them\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name\"),\n frameA: z.number().int().min(0).describe(\"First frame number\"),\n frameB: z.number().int().min(0).describe(\"Second frame number\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frameA, frameB }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) {\n return err(`State \"${stateName}\" not found`);\n }\n\n const resolvedA = resolveFrame(doc, stateName, frameA);\n const resolvedB = resolveFrame(doc, stateName, frameB);\n\n const changes: Array<{\n layerId: string;\n property: string;\n from: unknown;\n to: unknown;\n }> = [];\n\n for (const layerB of resolvedB.layers) {\n const layerA = resolvedA.layers.find(l => l.id === layerB.id);\n const propsA = layerA?.computedProperties ?? {};\n const propsB = layerB.computedProperties;\n\n // All property keys from both frames\n const allKeys = new Set([...Object.keys(propsA), ...Object.keys(propsB)]);\n for (const key of allKeys) {\n const valA = (propsA as Record<string, unknown>)[key];\n const valB = (propsB as Record<string, unknown>)[key];\n if (valA !== valB) {\n changes.push({ layerId: layerB.id, property: key, from: valA, to: valB });\n }\n }\n }\n\n return ok({\n stateName,\n frameA,\n frameB,\n changeCount: changes.length,\n changes,\n });\n },\n );\n\n // ── atelier_batch_preview ──────────────────────────────────\n server.tool(\n \"atelier_batch_preview\",\n \"Preview multiple frames at once — reduces round-trips for scrubbing or timeline inspection\",\n {\n id: z.string().describe(\"Document ID\"),\n stateName: z.string().describe(\"State name to preview\"),\n frames: z.array(z.number().int().min(0)).min(1).max(60).describe(\"Array of frame numbers to resolve (max 60)\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id, stateName, frames }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (!doc.states[stateName]) {\n return err(`State \"${stateName}\" not found`);\n }\n\n const start = performance.now();\n\n const results = frames.map(frame => {\n const resolved = resolveFrame(doc, stateName, frame);\n return {\n frame,\n layers: resolved.layers.map(rl => ({\n id: rl.id,\n computedProperties: rl.computedProperties,\n })),\n };\n });\n\n const totalTimeMs = performance.now() - start;\n\n return ok({\n stateName,\n duration: doc.states[stateName].duration,\n frameCount: frames.length,\n totalTimeMs: Math.round(totalTimeMs * 1000) / 1000,\n avgTimeMs: Math.round((totalTimeMs / frames.length) * 1000) / 1000,\n frames: results,\n });\n },\n );\n\n // ── atelier_complexity ─────────────────────────────────────\n server.tool(\n \"atelier_complexity\",\n \"Analyze document complexity — layer count, delta count, expression usage, state hierarchy depth\",\n {\n id: z.string().describe(\"Document ID\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ id }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const layerCount = doc.layers.length;\n const stateCount = Object.keys(doc.states).length;\n const assetCount = doc.assets ? Object.keys(doc.assets).length : 0;\n const variableCount = doc.variables ? Object.keys(doc.variables).length : 0;\n\n let totalDeltas = 0;\n let totalExpressions = 0;\n let maxStateDuration = 0;\n let totalInteractions = 0;\n\n const stateDetails: Array<{\n name: string;\n duration: number;\n deltaCount: number;\n expressionCount: number;\n hasParent: boolean;\n transitionCount: number;\n }> = [];\n\n for (const [name, state] of Object.entries(doc.states)) {\n const deltaCount = state.deltas.length;\n totalDeltas += deltaCount;\n\n const expressionCount = state.deltas.filter(\n d => (typeof d.from === \"object\" && d.from !== null && \"expr\" in d.from) ||\n (typeof d.to === \"object\" && d.to !== null && \"expr\" in d.to)\n ).length;\n totalExpressions += expressionCount;\n\n if (state.duration > maxStateDuration) maxStateDuration = state.duration;\n\n stateDetails.push({\n name,\n duration: state.duration,\n deltaCount,\n expressionCount,\n // hasAudio removed in v1.0 — audio is no longer per-state, it's an\n // AudioVisual layer. Audio-layer counts appear in the top-level\n // layer stats below.\n hasParent: !!state.parent,\n transitionCount: state.transitions ? Object.keys(state.transitions).length : 0,\n });\n }\n\n for (const layer of doc.layers) {\n if (layer.interactions) totalInteractions += layer.interactions.length;\n }\n\n // Compute hierarchy depth\n let maxHierarchyDepth = 0;\n for (const [name] of Object.entries(doc.states)) {\n let depth = 0;\n let current = name;\n const visited = new Set<string>();\n while (doc.states[current]?.parent && !visited.has(current)) {\n visited.add(current);\n current = doc.states[current].parent!;\n depth++;\n }\n if (depth > maxHierarchyDepth) maxHierarchyDepth = depth;\n }\n\n // Unique animated properties\n const animatedProperties = new Set<string>();\n for (const state of Object.values(doc.states)) {\n for (const delta of state.deltas) {\n animatedProperties.add(delta.property);\n }\n }\n\n return ok({\n layerCount,\n stateCount,\n totalDeltas,\n totalExpressions,\n totalInteractions,\n assetCount,\n variableCount,\n maxStateDuration,\n maxHierarchyDepth,\n uniqueAnimatedProperties: [...animatedProperties],\n stateDetails,\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Overlay layer tools (handle, page-number)\n//\n// Convenience tools for agents that build social-feed style overlays\n// (creator handle, \"1/5\" page indicator). Both tools tag emitted layers\n// \"overlay\" so re-running recipe pipelines (applyRecipeToOverlay) won't\n// destroy user-tweaked overlays — the same tag-namespace isolation\n// invariant used by silence-trim and caption layers.\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Layer, TextStyle } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nconst AnchorEnum = z.enum([\"top-left\", \"top-right\", \"bottom-left\", \"bottom-right\"]);\n\n// Mirrors recipe OverlayTextStyle (snake_case). Kept loose — partial overrides\n// merge over the runtime defaults below.\nconst OverlayStyleSchema = z.object({\n font_family: z.string().optional(),\n font_size: z.number().positive().optional(),\n font_weight: z.union([z.number(), z.enum([\"normal\", \"bold\"])]).optional(),\n color: z.string().optional(),\n}).optional();\n\nconst DEFAULT_OVERLAY_MARGIN = 24;\nconst DEFAULT_TEXT_STYLE: TextStyle = {\n fontFamily: \"Inter\",\n fontSize: 24,\n fontWeight: 600,\n color: \"#F5F5F7\",\n};\n\ntype Anchor = z.infer<typeof AnchorEnum>;\ntype OverlayStyleInput = {\n font_family?: string;\n font_size?: number;\n font_weight?: number | \"normal\" | \"bold\";\n color?: string;\n};\n\nfunction anchorToFrame(\n anchor: Anchor,\n canvas: AtelierDocument[\"canvas\"],\n margin: number,\n): { frame: { x: number; y: number }; anchorPoint: { x: number; y: number } } {\n switch (anchor) {\n case \"top-left\":\n return { frame: { x: margin, y: margin }, anchorPoint: { x: 0, y: 0 } };\n case \"top-right\":\n return { frame: { x: canvas.width - margin, y: margin }, anchorPoint: { x: 1, y: 0 } };\n case \"bottom-left\":\n return { frame: { x: margin, y: canvas.height - margin }, anchorPoint: { x: 0, y: 1 } };\n case \"bottom-right\":\n return {\n frame: { x: canvas.width - margin, y: canvas.height - margin },\n anchorPoint: { x: 1, y: 1 },\n };\n }\n}\n\nfunction mergeStyle(style: OverlayStyleInput | undefined): TextStyle {\n return {\n fontFamily: style?.font_family ?? DEFAULT_TEXT_STYLE.fontFamily,\n fontSize: style?.font_size ?? DEFAULT_TEXT_STYLE.fontSize,\n fontWeight: style?.font_weight ?? DEFAULT_TEXT_STYLE.fontWeight,\n color: style?.color ?? DEFAULT_TEXT_STYLE.color,\n };\n}\n\n/**\n * Render a page-number format template — substitutes {current} / {total}\n * placeholders including zero-pad forms ({current:02d}, {total:02d}).\n * Mirrors recipe.ts's renderPageNumberFormat exactly (intentional duplication\n * to keep the mcp package independent of the cli package).\n */\nfunction renderPageNumberFormat(format: string, currentIndex: number, totalCount: number): string {\n return format.replace(\n /\\{(current|total)(?::0(\\d+)d)?\\}/g,\n (_, name: string, padWidth?: string) => {\n const value = name === \"current\" ? currentIndex : totalCount;\n const str = String(value);\n if (padWidth) {\n const width = parseInt(padWidth, 10);\n return str.padStart(width, \"0\");\n }\n return str;\n },\n );\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_handle ──────────────────────────────────────\n server.tool(\n \"atelier_add_handle\",\n \"Add an anchored creator-handle TextVisual overlay layer (tag: overlay)\",\n {\n id: z.string().describe(\"Document ID\"),\n text: z.string().min(1).describe(\"Handle text, e.g. \\\"@username\\\"\"),\n anchor: AnchorEnum.describe(\"Anchored corner\"),\n margin: z.number().nonnegative().optional().describe(\"Px from anchored edges (default 24)\"),\n style: OverlayStyleSchema.describe(\"Text style overrides (snake_case to match recipe)\"),\n layerId: z.string().optional().describe(\"Layer ID (default: overlay-handle)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, text, anchor, margin, style, layerId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const targetId = layerId ?? \"overlay-handle\";\n if (doc.layers.some((l) => l.id === targetId)) {\n return err(`Layer \"${targetId}\" already exists in document \"${id}\"`);\n }\n\n const m = margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(anchor, doc.canvas, m);\n const layer: Layer = {\n id: targetId,\n tags: [\"overlay\"],\n visual: { type: \"text\", content: text, style: mergeStyle(style) },\n frame,\n bounds: { width: 600, height: 80 },\n anchorPoint,\n };\n\n doc.layers.push(layer);\n store.set(id, doc);\n return ok({ layerId: targetId, layer });\n },\n );\n\n // ── atelier_add_page_number ─────────────────────────────────\n server.tool(\n \"atelier_add_page_number\",\n \"Add an anchored page-number TextVisual overlay layer (tag: overlay). \" +\n \"Substitutes {current} / {total} (and zero-pad forms {current:02d} / {total:02d}) into format.\",\n {\n id: z.string().describe(\"Document ID\"),\n format: z.string().min(1).describe(\"Format string, e.g. \\\"{current}/{total}\\\" or \\\"{current:02d}/{total:02d}\\\"\"),\n anchor: AnchorEnum.describe(\"Anchored corner\"),\n currentIndex: z.number().int().nonnegative().describe(\"1-based current index\"),\n totalCount: z.number().int().positive().describe(\"Total count\"),\n margin: z.number().nonnegative().optional().describe(\"Px from anchored edges (default 24)\"),\n style: OverlayStyleSchema.describe(\"Text style overrides (snake_case to match recipe)\"),\n layerId: z.string().optional().describe(\"Layer ID (default: overlay-page-number)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ id, format, anchor, currentIndex, totalCount, margin, style, layerId }) => {\n const result = getDoc(store, id);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const targetId = layerId ?? \"overlay-page-number\";\n if (doc.layers.some((l) => l.id === targetId)) {\n return err(`Layer \"${targetId}\" already exists in document \"${id}\"`);\n }\n\n const content = renderPageNumberFormat(format, currentIndex, totalCount);\n const m = margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(anchor, doc.canvas, m);\n const layer: Layer = {\n id: targetId,\n tags: [\"overlay\"],\n visual: { type: \"text\", content, style: mergeStyle(style) },\n frame,\n bounds: { width: 200, height: 80 },\n anchorPoint,\n };\n\n doc.layers.push(layer);\n store.set(id, doc);\n return ok({ layerId: targetId, layer, rendered: content });\n },\n );\n}\n","// @a-company/atelier-mcp — Studio Recipe tools (list, get, validate, save, apply)\n//\n// Conversational view/edit surface for Studio Recipes. Wraps the recipe\n// load/validate/serialize/apply pipeline so an agent can show, explain, edit,\n// and apply recipes without shelling out to the CLI.\n//\n// Dependency note: the canonical recipe pure-functions live in the CLI package\n// (@a-company/atelier — packages/cli/src/lib/recipe.ts). The MCP package does\n// NOT depend on the CLI package (importing it would risk a cli↔mcp dependency\n// cycle), so the thin load/validate/serialize wrappers and the overlay_rules\n// translator are re-implemented here on top of @a-company/atelier-schema's\n// validateRecipe + the `yaml` package. This mirrors the existing intentional\n// duplication of renderPageNumberFormat in overlays.ts.\n\nimport { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from \"node:fs\";\nimport { join, resolve, isAbsolute, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { validateRecipe } from \"@a-company/atelier-schema\";\nimport type {\n AtelierDocument,\n Layer,\n StudioRecipe,\n OverlayAnchor,\n OverlayTextStyle,\n OverlayPageNumberRule,\n} from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string, extra?: Record<string, unknown>) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: message, ...extra }) }],\n isError: true as const,\n };\n}\n\n// ─── Recipe load / validate / serialize (re-implemented from cli/recipe.ts) ───\n\ninterface LoadedRecipe {\n recipe: StudioRecipe;\n /** Absolute path the recipe was read from */\n path: string;\n /** Warnings from validateRecipe (e.g. reserved-field usage) */\n warnings: string[];\n}\n\n/**\n * Resolve a recipe reference to an absolute path. Mirrors recipe.ts's\n * resolveRecipePath: absolute or slash-bearing paths load literally; bare\n * names resolve against <projectDir>/.atelier/recipes/ then ~/.atelier/recipes/.\n */\nfunction resolveRecipePath(pathOrName: string, projectDir: string): string {\n if (isAbsolute(pathOrName) || pathOrName.includes(\"/\") || pathOrName.includes(\"\\\\\")) {\n return resolve(pathOrName);\n }\n\n const candidates: string[] = [];\n const exts = [\".recipe.yaml\", \".recipe.json\", \".yaml\", \".yml\", \".json\"];\n\n const projectRecipesDir = join(resolve(projectDir), \".atelier\", \"recipes\");\n for (const ext of exts) candidates.push(join(projectRecipesDir, `${pathOrName}${ext}`));\n const userRecipesDir = join(homedir(), \".atelier\", \"recipes\");\n for (const ext of exts) candidates.push(join(userRecipesDir, `${pathOrName}${ext}`));\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) return candidate;\n }\n\n throw new Error(\n `Recipe \"${pathOrName}\" not found. Looked in:\\n${candidates.map((c) => ` ${c}`).join(\"\\n\")}`,\n );\n}\n\n/** Parse raw recipe text — JSON for .json, YAML otherwise (YAML is a JSON superset). */\nfunction parseRecipeText(raw: string, path: string): unknown {\n if (path.endsWith(\".json\")) return JSON.parse(raw);\n return parseYaml(raw);\n}\n\n/** Load + validate a recipe from a path or name. Throws on not-found / invalid. */\nfunction loadRecipe(pathOrName: string, projectDir: string): LoadedRecipe {\n const path = resolveRecipePath(pathOrName, projectDir);\n const raw = readFileSync(path, \"utf-8\");\n const parsed = parseRecipeText(raw, path);\n\n const result = validateRecipe(parsed);\n if (!result.success) {\n const msg = result.errors.map((e) => ` ${e.path}: ${e.message}`).join(\"\\n\");\n throw new Error(`Invalid recipe at ${path}:\\n${msg}`);\n }\n\n return { recipe: result.data, path, warnings: result.warnings ?? [] };\n}\n\n/** Serialize a recipe object back to YAML. */\nfunction recipeToYaml(recipe: StudioRecipe): string {\n return stringifyYaml(recipe);\n}\n\n// ─── Overlay translator (re-implemented from cli/recipe.ts) ───────────────────\n//\n// Translates recipe.overlay_rules → tag-isolated TextVisual layers. Only\n// \"overlay\"-tagged layers are touched; everything else passes through. Re-apply\n// is idempotent (prior overlay set dropped before fresh set appended).\n\nconst DEFAULT_OVERLAY_MARGIN = 24;\nconst DEFAULT_OVERLAY_TEXT_STYLE = {\n fontFamily: \"Inter\",\n fontSize: 24,\n fontWeight: 600 as const,\n color: \"#F5F5F7\",\n};\nconst HANDLE_LAYER_ID = \"overlay-handle\";\nconst PAGE_NUMBER_LAYER_ID = \"overlay-page-number\";\n\ninterface ApplyOverlayContext {\n currentIndex?: number;\n totalCount?: number;\n}\n\ninterface OverlayApplyResult {\n doc: AtelierDocument;\n warnings: string[];\n}\n\nfunction applyRecipeToOverlay(\n doc: AtelierDocument,\n recipe: StudioRecipe,\n ctx?: ApplyOverlayContext,\n): OverlayApplyResult {\n const preserved = doc.layers.filter((l) => !(l.tags ?? []).includes(\"overlay\"));\n const overlayLayers: Layer[] = [];\n const warnings: string[] = [];\n\n const rules = recipe.overlay_rules;\n if (!rules) {\n return { doc: { ...doc, layers: preserved }, warnings };\n }\n\n if (rules.handle) {\n overlayLayers.push(buildHandleLayer(rules.handle, doc.canvas));\n }\n\n if (rules.page_number) {\n if (ctx?.currentIndex != null && ctx?.totalCount != null) {\n overlayLayers.push(\n buildPageNumberLayer(rules.page_number, doc.canvas, ctx.currentIndex, ctx.totalCount),\n );\n } else {\n warnings.push(\n \"recipe.overlay_rules.page_number is present but currentIndex/totalCount \" +\n \"were not provided — the page_number layer was skipped.\",\n );\n }\n }\n\n return { doc: { ...doc, layers: [...preserved, ...overlayLayers] }, warnings };\n}\n\nfunction buildHandleLayer(\n rule: { text: string; anchor: OverlayAnchor; margin?: number; style?: OverlayTextStyle },\n canvas: AtelierDocument[\"canvas\"],\n): Layer {\n const margin = rule.margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(rule.anchor, canvas, margin);\n return {\n id: HANDLE_LAYER_ID,\n tags: [\"overlay\"],\n visual: { type: \"text\", content: rule.text, style: mergeOverlayStyle(rule.style) },\n frame,\n bounds: { width: 600, height: 80 },\n anchorPoint,\n };\n}\n\nfunction buildPageNumberLayer(\n rule: OverlayPageNumberRule,\n canvas: AtelierDocument[\"canvas\"],\n currentIndex: number,\n totalCount: number,\n): Layer {\n const margin = rule.margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(rule.anchor, canvas, margin);\n return {\n id: PAGE_NUMBER_LAYER_ID,\n tags: [\"overlay\"],\n visual: {\n type: \"text\",\n content: renderPageNumberFormat(rule.format, currentIndex, totalCount),\n style: mergeOverlayStyle(rule.style),\n },\n frame,\n bounds: { width: 200, height: 80 },\n anchorPoint,\n };\n}\n\nfunction anchorToFrame(\n anchor: OverlayAnchor,\n canvas: AtelierDocument[\"canvas\"],\n margin: number,\n): { frame: { x: number; y: number }; anchorPoint: { x: number; y: number } } {\n switch (anchor) {\n case \"top-left\":\n return { frame: { x: margin, y: margin }, anchorPoint: { x: 0, y: 0 } };\n case \"top-right\":\n return { frame: { x: canvas.width - margin, y: margin }, anchorPoint: { x: 1, y: 0 } };\n case \"bottom-left\":\n return { frame: { x: margin, y: canvas.height - margin }, anchorPoint: { x: 0, y: 1 } };\n case \"bottom-right\":\n return {\n frame: { x: canvas.width - margin, y: canvas.height - margin },\n anchorPoint: { x: 1, y: 1 },\n };\n }\n}\n\nfunction mergeOverlayStyle(\n style: OverlayTextStyle | undefined,\n): { fontFamily: string; fontSize: number; fontWeight: number | \"normal\" | \"bold\"; color: string } {\n return {\n fontFamily: style?.font_family ?? DEFAULT_OVERLAY_TEXT_STYLE.fontFamily,\n fontSize: style?.font_size ?? DEFAULT_OVERLAY_TEXT_STYLE.fontSize,\n fontWeight: style?.font_weight ?? DEFAULT_OVERLAY_TEXT_STYLE.fontWeight,\n color: style?.color ?? DEFAULT_OVERLAY_TEXT_STYLE.color,\n };\n}\n\nfunction renderPageNumberFormat(format: string, currentIndex: number, totalCount: number): string {\n return format.replace(\n /\\{(current|total)(?::0(\\d+)d)?\\}/g,\n (_, name: string, padWidth?: string) => {\n const value = name === \"current\" ? currentIndex : totalCount;\n const str = String(value);\n if (padWidth) return str.padStart(parseInt(padWidth, 10), \"0\");\n return str;\n },\n );\n}\n\n// ─── Discovery ────────────────────────────────────────────────────────────────\n\nconst RECIPE_EXTS = [\".recipe.yaml\", \".recipe.yml\", \".recipe.json\"];\n\nfunction isRecipeFile(name: string): boolean {\n return RECIPE_EXTS.some((ext) => name.endsWith(ext));\n}\n\n/** List recipe files in a directory (non-recursive). Returns absolute paths. */\nfunction listRecipesIn(dir: string): Array<{ name: string; path: string }> {\n if (!existsSync(dir)) return [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return [];\n }\n return entries\n .filter(isRecipeFile)\n .map((name) => ({ name, path: join(dir, name) }))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_recipe_list ─────────────────────────────────────\n server.tool(\n \"atelier_recipe_list\",\n \"List discoverable Studio Recipes — project-local <projectDir>/.atelier/recipes/*.recipe.* \" +\n \"plus ~/.atelier/recipes/*.recipe.*. Returns { name, path } entries with absolute paths.\",\n {\n projectDir: z.string().optional().describe(\"Project root to search (default: process.cwd())\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ projectDir }) => {\n const root = resolve(projectDir ?? process.cwd());\n const projectRecipes = listRecipesIn(join(root, \".atelier\", \"recipes\"));\n const userRecipes = listRecipesIn(join(homedir(), \".atelier\", \"recipes\"));\n // Project recipes take precedence; de-dupe by basename.\n const seen = new Set(projectRecipes.map((r) => r.name));\n const recipes = [...projectRecipes, ...userRecipes.filter((r) => !seen.has(r.name))];\n return ok({ count: recipes.length, recipes });\n },\n );\n\n // ── atelier_recipe_get ──────────────────────────────────────\n server.tool(\n \"atelier_recipe_get\",\n \"Load a recipe and return BOTH the parsed object and its serialized YAML text \" +\n \"(so the agent can show/explain it), plus any validation warnings.\",\n {\n path: z.string().describe(\"Recipe path or bare name (resolved like the CLI)\"),\n projectDir: z.string().optional().describe(\"Project root for name resolution (default: process.cwd())\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ path, projectDir }) => {\n const root = resolve(projectDir ?? process.cwd());\n try {\n const loaded = loadRecipe(path, root);\n return ok({\n path: loaded.path,\n recipe: loaded.recipe as unknown as Record<string, unknown>,\n yaml: recipeToYaml(loaded.recipe),\n warnings: loaded.warnings,\n });\n } catch (e) {\n return err((e as Error).message);\n }\n },\n );\n\n // ── atelier_recipe_validate ─────────────────────────────────\n server.tool(\n \"atelier_recipe_validate\",\n \"Validate a recipe from a path OR inline YAML text. Returns { success, warnings, errors }.\",\n {\n path: z.string().optional().describe(\"Recipe path or bare name to validate\"),\n yaml: z.string().optional().describe(\"Inline YAML text to validate (alternative to path)\"),\n projectDir: z.string().optional().describe(\"Project root for name resolution (default: process.cwd())\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ path, yaml, projectDir }) => {\n if (!path && yaml === undefined) {\n return err(\"Provide either `path` or `yaml` to validate\");\n }\n const root = resolve(projectDir ?? process.cwd());\n\n let parsed: unknown;\n try {\n if (yaml !== undefined) {\n parsed = parseYaml(yaml);\n } else {\n const resolved = resolveRecipePath(path as string, root);\n parsed = parseRecipeText(readFileSync(resolved, \"utf-8\"), resolved);\n }\n } catch (e) {\n return ok({ valid: false, warnings: [], errors: [{ path: \"(yaml)\", message: (e as Error).message }] });\n }\n\n const result = validateRecipe(parsed);\n if (!result.success) {\n return ok({ valid: false, warnings: [], errors: result.errors });\n }\n return ok({ valid: true, warnings: result.warnings ?? [], errors: [] });\n },\n );\n\n // ── atelier_recipe_save ─────────────────────────────────────\n server.tool(\n \"atelier_recipe_save\",\n \"Write a recipe to disk. Accepts a recipe object (serialized via YAML) OR raw YAML text. \" +\n \"Validates BEFORE writing and REFUSES to write an invalid recipe (returns an error with the \" +\n \"validation issues). Creates parent directories as needed.\",\n {\n path: z.string().describe(\"Absolute or relative file path to write the recipe to\"),\n recipe: z.record(z.unknown()).optional().describe(\"Recipe object (will be serialized to YAML)\"),\n yaml: z.string().optional().describe(\"Raw YAML text (alternative to `recipe`)\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ path, recipe, yaml }) => {\n if (recipe === undefined && yaml === undefined) {\n return err(\"Provide either `recipe` (object) or `yaml` (text) to save\");\n }\n\n // Materialize the recipe object + its YAML text.\n let parsed: unknown;\n let yamlText: string;\n if (yaml !== undefined) {\n yamlText = yaml;\n try {\n parsed = parseYaml(yaml);\n } catch (e) {\n return err(`YAML parse error: ${(e as Error).message}`);\n }\n } else {\n parsed = recipe;\n yamlText = stringifyYaml(recipe);\n }\n\n // Validate — refuse to write an invalid recipe.\n const result = validateRecipe(parsed);\n if (!result.success) {\n return err(\"Refusing to write an invalid recipe\", { errors: result.errors });\n }\n\n const absPath = resolve(path);\n try {\n mkdirSync(dirname(absPath), { recursive: true });\n writeFileSync(absPath, yamlText, \"utf-8\");\n } catch (e) {\n return err(`Failed to write recipe: ${(e as Error).message}`);\n }\n\n return ok({ path: absPath, warnings: result.warnings ?? [] });\n },\n );\n\n // ── atelier_recipe_apply ────────────────────────────────────\n server.tool(\n \"atelier_recipe_apply\",\n \"Apply a recipe's overlay_rules to an in-store document (handle + page-number overlays). \" +\n \"Accepts a recipe object OR a path/name. The result is stored back with source=\\\"llm\\\". \" +\n \"NOTE: only overlay_rules are applied here — silence-trim / transcribe / caption application \" +\n \"remain CLI-only. page_number overlays require currentIndex + totalCount; if a recipe requests \" +\n \"page_number without them, that layer is skipped and a warning is returned.\",\n {\n documentId: z.string().describe(\"In-store document ID to apply the recipe to\"),\n path: z.string().optional().describe(\"Recipe path or bare name (alternative to `recipe`)\"),\n recipe: z.record(z.unknown()).optional().describe(\"Recipe object (alternative to `path`)\"),\n projectDir: z.string().optional().describe(\"Project root for name resolution (default: process.cwd())\"),\n currentIndex: z.number().int().nonnegative().optional().describe(\"1-based carousel index for page_number\"),\n totalCount: z.number().int().positive().optional().describe(\"Total carousel size for page_number\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, path, recipe, projectDir, currentIndex, totalCount }) => {\n const result = getDoc(store, documentId);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n if (path === undefined && recipe === undefined) {\n return err(\"Provide either `path` or `recipe` to apply\");\n }\n\n // Resolve the recipe object (validated either way).\n let resolvedRecipe: StudioRecipe;\n if (recipe !== undefined) {\n const validated = validateRecipe(recipe);\n if (!validated.success) {\n return err(\"Invalid recipe\", { errors: validated.errors });\n }\n resolvedRecipe = validated.data;\n } else {\n const root = resolve(projectDir ?? process.cwd());\n try {\n resolvedRecipe = loadRecipe(path as string, root).recipe;\n } catch (e) {\n return err((e as Error).message);\n }\n }\n\n const { doc: updated, warnings } = applyRecipeToOverlay(doc, resolvedRecipe, {\n currentIndex,\n totalCount,\n });\n store.set(documentId, updated, \"llm\");\n\n return ok({\n documentId,\n warnings,\n layerCount: updated.layers.length,\n document: updated as unknown as Record<string, unknown>,\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Folder image ingestion tool\n//\n// Lets an agent point at a folder of images and pull them into a document as\n// registered assets + (optionally) fit-to-canvas ImageVisual layers.\n//\n// The layer-building + background-swap convention mirrors\n// @a-company/atelier-studio's image-drop helper (createImageLayerFromFile /\n// buildImageLayer), adapted from the browser File/dataURL path to a node\n// filesystem path. MCP does not depend on the studio package, so the logic is\n// duplicated here (same pattern as the recipe-tool / overlay duplication\n// elsewhere in this package). Aspect-fit (fitImageToCanvas) is intentionally\n// NOT reused here — see the dimension note below.\n//\n// Dimension note: we do NOT add an image-dimension dependency. Without natural\n// dimensions we cannot compute true aspect-fit, so each layer's bounds default\n// to a centered square of min(canvas.width, canvas.height). This is surfaced in\n// the tool description and in the response `note`.\n\nimport { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { resolve, join, basename, extname } from \"node:path\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { AtelierDocument, Layer } from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\nfunction getDoc(store: DocumentStore, id: string): { doc: AtelierDocument } | { error: string } {\n const doc = store.get(id);\n if (!doc) return { error: `Document \"${id}\" not found` };\n return { doc };\n}\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\nconst IMAGE_EXTS = new Set([\".png\", \".jpg\", \".jpeg\", \".webp\", \".gif\", \".svg\"]);\n\nfunction isImageFile(name: string): boolean {\n return IMAGE_EXTS.has(extname(name).toLowerCase());\n}\n\n/**\n * Minimal substring/`*`-glob match. Supports a single-segment glob (no path\n * separators) with `*` wildcards — enough for \"*.png\" / \"hero-*\". Returns true\n * for an undefined/empty pattern (match-all).\n */\nfunction matchesGlob(name: string, glob: string | undefined): boolean {\n if (!glob) return true;\n // Translate the glob to a RegExp: escape regex specials, then * → .*\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\*/g, \".*\").replace(/\\?/g, \".\");\n return new RegExp(`^${escaped}$`, \"i\").test(name);\n}\n\n/**\n * Derive a stable, filesystem-safe assetId from a filename, de-duped against a\n * set of already-used ids. \"hero shot.png\" → \"hero-shot\", colliding → \"-2\".\n */\nfunction deriveAssetId(filename: string, used: Set<string>): string {\n const stem = basename(filename, extname(filename));\n const base = stem\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"image\";\n let candidate = base;\n let n = 2;\n while (used.has(candidate)) {\n candidate = `${base}-${n}`;\n n++;\n }\n used.add(candidate);\n return candidate;\n}\n\n/** Pick a unique layer id `${prefix}-N` not colliding with existing layers. */\nfunction nextImageLayerId(existing: Set<string>, seq: number): string {\n let candidate = `image-${seq}`;\n let n = seq;\n while (existing.has(candidate)) {\n n++;\n candidate = `image-${n}`;\n }\n existing.add(candidate);\n return candidate;\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_import_images ───────────────────────────────────\n server.tool(\n \"atelier_import_images\",\n \"Import every image in a folder into a document. Registers each as an asset and, \" +\n \"unless asLayers is false, creates one fit-to-canvas ImageVisual layer per image \" +\n \"(centered). Extensions: .png .jpg .jpeg .webp .gif .svg. Optional glob filters by \" +\n \"filename (e.g. \\\"*.png\\\"); results are sorted by name. If the folder has exactly one \" +\n \"image AND the doc's layer[0] is the welcome \\\"background\\\" placeholder, that image \" +\n \"replaces the placeholder in place. Asset src is the absolute file path. \" +\n \"Layer bounds default to a centered min(canvas.w, canvas.h) square because natural \" +\n \"image dimensions are not measured (no image-dimension dependency).\",\n {\n documentId: z.string().describe(\"In-store document ID to import into\"),\n dir: z.string().describe(\"Directory containing the images\"),\n glob: z.string().optional().describe(\"Optional filename glob, e.g. \\\"*.png\\\" (default: all images)\"),\n asLayers: z.boolean().optional().describe(\"Create layers per image (default: true). false = register assets only.\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, dir, glob, asLayers }) => {\n const result = getDoc(store, documentId);\n if (\"error\" in result) return err(result.error);\n const { doc } = result;\n\n const absDir = resolve(dir);\n if (!existsSync(absDir)) return err(`Directory \"${absDir}\" does not exist`);\n if (!statSync(absDir).isDirectory()) return err(`Path \"${absDir}\" is not a directory`);\n\n const files = readdirSync(absDir)\n .filter((name) => isImageFile(name) && matchesGlob(name, glob))\n .sort((a, b) => a.localeCompare(b));\n\n if (files.length === 0) {\n return err(`No image files matched in \"${absDir}\"${glob ? ` (glob: ${glob})` : \"\"}`);\n }\n\n const makeLayers = asLayers !== false;\n const canvas = doc.canvas;\n const square = Math.min(canvas.width, canvas.height);\n\n // Background-swap is only allowed for a single-image import (mirrors the\n // welcome-placeholder convention from the Studio image-drop helper).\n const allowBackgroundSwap = files.length === 1 && doc.layers[0]?.id === \"background\";\n\n // Copy-on-write: build a NEW doc with cloned assets + layers and store it\n // once at the end (mirrors applyRecipeToOverlay). A concurrent onChange\n // reader (the studio bridge) must never observe a half-mutated document.\n const newAssets: NonNullable<AtelierDocument[\"assets\"]> = { ...(doc.assets ?? {}) };\n const newLayers: Layer[] = [...doc.layers];\n\n const usedAssetIds = new Set(Object.keys(newAssets));\n const existingLayerIds = new Set(newLayers.map((l) => l.id));\n\n const assetIds: string[] = [];\n const layerIds: string[] = [];\n\n let layerSeq = newLayers.length + 1;\n for (const file of files) {\n const absPath = join(absDir, file);\n const assetId = deriveAssetId(file, usedAssetIds);\n newAssets[assetId] = { type: \"image\", src: absPath, description: file };\n assetIds.push(assetId);\n\n if (!makeLayers) continue;\n\n const layerId = nextImageLayerId(existingLayerIds, layerSeq);\n layerSeq++;\n\n const layer: Layer = {\n id: layerId,\n visual: { type: \"image\", assetId, src: absPath },\n frame: { x: canvas.width / 2, y: canvas.height / 2 },\n bounds: { width: square, height: square },\n anchorPoint: { x: 0.5, y: 0.5 },\n opacity: 1,\n };\n\n if (allowBackgroundSwap) {\n // Single image filling the welcome placeholder — swap in place so any\n // existing overlays stay on top.\n newLayers[0] = layer;\n } else {\n // Bottom of the z-stack (renderer paints index 0 first), behind\n // existing overlays — matches the Studio drop convention.\n newLayers.unshift(layer);\n }\n layerIds.push(layerId);\n }\n\n const newDoc: AtelierDocument = { ...doc, assets: newAssets, layers: newLayers };\n store.set(documentId, newDoc, \"llm\");\n\n return ok({\n imported: files.length,\n assetIds,\n layerIds,\n asLayers: makeLayers,\n note:\n \"Layer bounds default to a centered square (min canvas dimension) — \" +\n \"natural image dimensions are not measured.\",\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Mind-map query (stub / Phase 3)\n//\n// Resolves a typed asset slot against the creator's LOCAL asset library by\n// walking the project directory and returning paths whose extension matches\n// the slot `kind`. This is the minimum-viable surface called by Lux and Iris\n// (see .paradigm/personas/{lux,iris}/persona.yaml) — Phase 4 builds the\n// indexed/curated version (TD-229, TD-271, TD-540).\n//\n// Scope rules baked in here (do NOT expand without re-reading the Phase 3\n// reconciliation notes in docs/keynote/paradigm/phase-3-reconciliation-notes.md):\n//\n// - Pure read. No writes, no store mutations. The `store` parameter is\n// accepted for symmetry with the other `register*Tools` signatures but is\n// intentionally unused; querying the mind-map never touches the live\n// document.\n// - Local-only. Per TD-271 we never reach outside the project; the walk is\n// rooted at <projectDir> and confined to its subtree.\n// - No persistent index. Every call walks the directory from scratch. A\n// SQLite-backed index, semantic search, and the `atelier mind-map reindex`\n// verb all live in Phase 4. Keep this file small.\n//\n// Walk order (first match wins): <projectDir>/.atelier/mind-map/, then\n// <projectDir>/assets/, then <projectDir>/ itself. Depth is capped at 4\n// levels below the chosen root to keep pathological recursions (deep nests,\n// symlink loops) bounded.\n\nimport { existsSync, statSync, readdirSync } from \"node:fs\";\nimport { resolve, join, basename, extname } from \"node:path\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { SlotKindSchema, type SlotKind } from \"@a-company/atelier-schema\";\nimport type { DocumentStore } from \"../store.js\";\n\n// ─── Response envelope helpers (mirror import-images.ts) ─────────────────────\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], isError: true as const };\n}\n\n// ─── Kind → extension map ─────────────────────────────────────────────────────\n//\n// Hardcoded; the closed SlotKind enum keeps this table bounded. `text` resolves\n// at composition time, not from disk (see the per-call `note`). `voice`\n// reuses the audio extensions (TTS voice samples are audio files); `logo`\n// reuses the image extensions.\n\nconst KIND_EXTENSIONS: Record<SlotKind, ReadonlySet<string>> = {\n image: new Set([\".png\", \".jpg\", \".jpeg\", \".webp\", \".gif\", \".svg\", \".avif\"]),\n video: new Set([\".mp4\", \".mov\", \".webm\", \".mkv\", \".avi\"]),\n audio: new Set([\".mp3\", \".wav\", \".m4a\", \".ogg\", \".flac\", \".aac\"]),\n font: new Set([\".ttf\", \".otf\", \".woff\", \".woff2\"]),\n text: new Set<string>(), // empty by design — handled with a per-call note\n voice: new Set([\".mp3\", \".wav\", \".m4a\", \".ogg\", \".flac\", \".aac\"]),\n logo: new Set([\".png\", \".jpg\", \".jpeg\", \".webp\", \".gif\", \".svg\", \".avif\"]),\n};\n\nconst TEXT_NOTE = \"text slots resolve at composition time, not from disk\";\n\n/** Max directory levels to descend BELOW the chosen search root. */\nconst MAX_DEPTH = 4;\n\n// ─── Walker ──────────────────────────────────────────────────────────────────\n\ninterface Candidate {\n /** Absolute path on disk. */\n path: string;\n /** basename(path) */\n name: string;\n /** mtimeMs for sort. */\n mtimeMs: number;\n /**\n * Segments of the path RELATIVE to the search root (excluding the basename),\n * used for hint matching against ancestor directory names. Bounded to the\n * search subtree so a hint like \"users\" cannot accidentally match because\n * the project lives under /Users/.\n */\n relDirSegments: string[];\n}\n\n/**\n * Pick the root directory to walk. First existing wins:\n * 1. <projectDir>/.atelier/mind-map/\n * 2. <projectDir>/assets/\n * 3. <projectDir> itself\n */\nfunction chooseSearchRoot(projectDir: string): string {\n const mindMap = join(projectDir, \".atelier\", \"mind-map\");\n if (existsSync(mindMap) && statSync(mindMap).isDirectory()) return mindMap;\n const assets = join(projectDir, \"assets\");\n if (existsSync(assets) && statSync(assets).isDirectory()) return assets;\n return projectDir;\n}\n\n/**\n * Walk `root` recursively up to MAX_DEPTH levels deep, collecting every file\n * (regular files only) with its mtime and relative directory segments. Symlinks\n * are followed via the default statSync, but the depth cap prevents loops from\n * exploding. Directories that fail to read (permission, transient races) are\n * skipped silently — the goal is a best-effort listing, not a filesystem\n * audit.\n *\n * `searchedDirs` is populated with every directory the walk actually entered\n * (absolute paths), so the caller can report what was scanned.\n */\nfunction walk(root: string, searchedDirs: string[]): Candidate[] {\n const out: Candidate[] = [];\n\n function recurse(dir: string, depth: number, relSegments: string[]): void {\n searchedDirs.push(dir);\n\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return; // unreadable dir → skip rather than crash the whole query\n }\n\n for (const entry of entries) {\n const abs = join(dir, entry);\n let stat;\n try {\n stat = statSync(abs);\n } catch {\n continue; // race / broken symlink → skip\n }\n\n if (stat.isDirectory()) {\n if (depth >= MAX_DEPTH) continue; // depth cap — do not descend further\n recurse(abs, depth + 1, [...relSegments, entry]);\n } else if (stat.isFile()) {\n out.push({\n path: abs,\n name: entry,\n mtimeMs: stat.mtimeMs,\n relDirSegments: relSegments,\n });\n }\n }\n }\n\n recurse(root, 0, []);\n return out;\n}\n\n// ─── Hint matching ────────────────────────────────────────────────────────────\n\n/**\n * Return the subset of `hints` that match the candidate. A hint matches when\n * its lowercased substring appears in either the candidate filename or any\n * ancestor directory name WITHIN the search root (case-insensitive). The\n * ancestor list is bounded to the search subtree so a hint like \"users\" can\n * never sneak in via the absolute filesystem path.\n */\nfunction matchedHints(candidate: Candidate, hints: string[]): string[] {\n const haystacks = [candidate.name.toLowerCase(), ...candidate.relDirSegments.map((s) => s.toLowerCase())];\n return hints.filter((h) => {\n const needle = h.toLowerCase();\n return haystacks.some((hs) => hs.includes(needle));\n });\n}\n\n// ─── Tool registration ───────────────────────────────────────────────────────\n\nconst DEFAULT_LIMIT = 20;\nconst MAX_LIMIT = 100;\n\nexport function register(server: McpServer, _store: DocumentStore): void {\n // _store is intentionally unused — see file header. Kept in the signature\n // for symmetry with the other register* functions and so callers in\n // index.ts don't have to special-case this registration.\n\n // ── atelier_mind_map_query ──────────────────────────────────\n server.tool(\n \"atelier_mind_map_query\",\n \"Resolve a typed asset slot against the creator's local asset library. Walks \" +\n \"<projectDir>/.atelier/mind-map/ (preferred), else <projectDir>/assets/, else \" +\n \"<projectDir> itself. Recursive with a depth cap of 4 levels. Filters by the \" +\n \"slot `kind` extension table (image, video, audio, font, voice, logo); `text` \" +\n \"returns no matches by design (text resolves at composition time). Optional \" +\n \"`hints` (case-insensitive substrings) narrow by filename or ancestor directory \" +\n \"name within the search root. Results sorted by mtime (most-recent first). \" +\n \"Pure read — does not touch the document store. Stub for Phase 4 mind-map.\",\n {\n projectDir: z\n .string()\n .describe(\"Absolute or cwd-relative path to the project root\"),\n kind: SlotKindSchema.describe(\n \"Slot kind from the closed SlotKind enum (image|video|audio|text|font|voice|logo)\",\n ),\n hints: z\n .array(z.string().min(1))\n .min(1)\n .optional()\n .describe(\n \"Optional case-insensitive substrings; a candidate must match at least one \" +\n \"against its filename or an ancestor directory name within the search root.\",\n ),\n limit: z\n .number()\n .int()\n .positive()\n .max(MAX_LIMIT)\n .optional()\n .describe(`Max matches to return (default ${DEFAULT_LIMIT}, max ${MAX_LIMIT})`),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ projectDir, kind, hints, limit }) => {\n const absProject = resolve(projectDir);\n if (!existsSync(absProject)) {\n return err(`projectDir \"${absProject}\" does not exist`);\n }\n if (!statSync(absProject).isDirectory()) {\n return err(`projectDir \"${absProject}\" is not a directory`);\n }\n\n const searchRoot = chooseSearchRoot(absProject);\n const searchedDirs: string[] = [];\n const candidates = walk(searchRoot, searchedDirs);\n\n // `text` slots don't resolve from disk — return the documented note plus\n // an empty match list. We still report the searched dirs so the caller\n // can see the walk would have run.\n if (kind === \"text\") {\n return ok({\n matches: [],\n searched_dirs: searchedDirs,\n total_candidates: candidates.length,\n note: TEXT_NOTE,\n });\n }\n\n const allowedExts = KIND_EXTENSIONS[kind];\n const kindMatched = candidates.filter((c) => allowedExts.has(extname(c.name).toLowerCase()));\n\n // When hints are provided, a candidate must match AT LEAST ONE of them.\n // When absent, all kind-matched candidates pass through.\n const hintFiltered = hints\n ? kindMatched\n .map((c) => ({ c, matched: matchedHints(c, hints) }))\n .filter(({ matched }) => matched.length > 0)\n : kindMatched.map((c) => ({ c, matched: [] as string[] }));\n\n // Most-recently-modified first.\n hintFiltered.sort((a, b) => b.c.mtimeMs - a.c.mtimeMs);\n\n const effectiveLimit = limit ?? DEFAULT_LIMIT;\n const limited = hintFiltered.slice(0, effectiveLimit);\n\n const matches = limited.map(({ c, matched }) => ({\n path: c.path,\n name: basename(c.path),\n kind,\n matched_hints: matched,\n }));\n\n return ok({\n matches,\n searched_dirs: searchedDirs,\n total_candidates: candidates.length,\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Effective transcript query.\n//\n// `atelier_get_effective_transcript` reads a project's raw transcript.json\n// and cuts.json from disk, applies cuts in-memory, and returns the\n// post-cut transcript. Pure read — never writes, never touches the\n// document store.\n//\n// Dependency note: the canonical `applyCuts` pure function lives in the CLI\n// package (`packages/cli/src/lib/transcript-model.ts`). MCP does NOT depend\n// on the CLI package (avoids the cli↔mcp cycle), so the derivation is\n// re-implemented here on top of @a-company/atelier-types. This mirrors the\n// existing intentional duplication of the recipe overlay translator in\n// recipes.ts and renderPageNumberFormat in overlays.ts.\n\nimport { existsSync, readFileSync, statSync, readdirSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { join, resolve } from \"node:path\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n CutEntry,\n TranscriptDerivedFrom,\n TranscriptSegment,\n TranscriptWord,\n VideoTranscript,\n} from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\n\n// ─── Response envelope (mirror mind-map.ts) ───────────────────────\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }],\n isError: true as const,\n };\n}\n\n// ─── Pure derivation (duplicated from cli/transcript-model.ts) ────\n\n/**\n * Apply cuts to a raw transcript and return the effective (post-cut)\n * transcript. Drops words whose `start` falls outside any kept range; shifts\n * surviving timestamps by the cumulative offset of the previous kept ranges.\n *\n * Mirrors `applyCuts` in `packages/cli/src/lib/transcript-model.ts` —\n * keep these in sync if the semantics change.\n */\nfunction applyCuts(\n transcript: VideoTranscript,\n cuts: CutEntry[],\n options: { transcriptName: string; cutsHash: string; derivedAt: string },\n): VideoTranscript {\n const sortedCuts = [...cuts].sort((a, b) => a.rawStart - b.rawStart);\n const keepRanges = sortedCuts.map((c) => ({\n start: Math.max(0, c.rawStart - c.paddingPre),\n end: c.rawEnd + c.paddingPost,\n }));\n\n function mapTime(t: number): number | null {\n let cumulativeOffset = 0;\n for (const r of keepRanges) {\n if (t < r.start) return null;\n if (t <= r.end) return t - r.start + cumulativeOffset;\n cumulativeOffset += r.end - r.start;\n }\n return null;\n }\n\n const newSegments: TranscriptSegment[] = [];\n for (const seg of transcript.segments) {\n const newWords: TranscriptWord[] = [];\n for (const w of seg.words) {\n const ns = mapTime(w.start);\n const ne = mapTime(w.end);\n if (ns === null || ne === null) continue;\n newWords.push({ ...w, start: ns, end: ne });\n }\n if (newWords.length === 0) continue;\n newSegments.push({\n text: seg.text,\n start: newWords[0].start,\n end: newWords[newWords.length - 1].end,\n words: newWords,\n });\n }\n\n const totalCutDurationS = keepRanges.reduce((sum, r) => sum + (r.end - r.start), 0);\n\n const derived_from: TranscriptDerivedFrom = {\n transcriptName: options.transcriptName,\n cutsHash: options.cutsHash,\n derivedAt: options.derivedAt,\n cutsApplied: sortedCuts.length,\n totalCutDurationS,\n };\n\n return {\n version: transcript.version,\n ...(transcript.language !== undefined && { language: transcript.language }),\n segments: newSegments,\n derived_from,\n };\n}\n\n/** Stable hash of the cuts list — mirrors `hashCuts` in cli/transcript-model.ts. */\nfunction hashCuts(cuts: CutEntry[]): string {\n const canonical = cuts.map((c) => [c.rawStart, c.rawEnd, c.paddingPre, c.paddingPost]);\n return createHash(\"sha256\").update(JSON.stringify(canonical)).digest(\"hex\").slice(0, 16);\n}\n\n// ─── Transcript file discovery ───────────────────────────────────\n\ninterface TranscriptCandidate {\n /** Absolute path on disk. */\n absPath: string;\n /** Filename as the caller should reference it (e.g. \"transcript.json\"). */\n name: string;\n}\n\n/**\n * Discover transcript file(s) in a project directory. Prefers the canonical\n * `transcript.json` at the project root; also accepts the forward-compat\n * shape `transcripts/<name>.json` documented in reconstruct.ts.\n */\nfunction discoverTranscripts(projectDir: string): TranscriptCandidate[] {\n const out: TranscriptCandidate[] = [];\n const canonical = join(projectDir, \"transcript.json\");\n if (existsSync(canonical) && statSync(canonical).isFile()) {\n out.push({ absPath: canonical, name: \"transcript.json\" });\n }\n const transcriptsDir = join(projectDir, \"transcripts\");\n if (existsSync(transcriptsDir) && statSync(transcriptsDir).isDirectory()) {\n try {\n const entries = readdirSync(transcriptsDir).filter((f) => f.endsWith(\".json\")).sort();\n for (const entry of entries) {\n out.push({\n absPath: join(transcriptsDir, entry),\n name: `transcripts/${entry}`,\n });\n }\n } catch {\n // Unreadable transcripts/ — ignore, the canonical path may still match.\n }\n }\n return out;\n}\n\n// ─── Tool registration ───────────────────────────────────────────\n\nexport function register(server: McpServer, _store: DocumentStore): void {\n // _store unused — pure read against local disk (mirrors mind-map.ts).\n\n server.tool(\n \"atelier_get_effective_transcript\",\n \"Read a project's raw transcript.json + cuts.json and return the post-cut \" +\n \"(effective) transcript — words inside cut gaps dropped, surviving timestamps \" +\n \"shifted to the trimmed timeline. Pure read; does not touch the document store. \" +\n \"When cuts.json is absent or has zero cuts, returns the raw transcript verbatim \" +\n \"(no `derived_from` stamp). Optional `transcriptName` disambiguates when the \" +\n \"project carries multiple transcripts (transcripts/*.json); without it, \" +\n \"transcript.json wins, and an error is returned if multiple sit in transcripts/.\",\n {\n projectDir: z.string().describe(\"Absolute or cwd-relative project root\"),\n transcriptName: z\n .string()\n .optional()\n .describe(\n \"Optional transcript filename (e.g. 'transcript.json' or \" +\n \"'transcripts/take-2.json'). Disambiguates multi-transcript projects.\",\n ),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ projectDir, transcriptName }) => {\n const absProject = resolve(projectDir);\n if (!existsSync(absProject)) {\n return err(`projectDir \"${absProject}\" does not exist`);\n }\n if (!statSync(absProject).isDirectory()) {\n return err(`projectDir \"${absProject}\" is not a directory`);\n }\n\n // Resolve which transcript file to load.\n let chosen: TranscriptCandidate | undefined;\n if (transcriptName !== undefined) {\n const absPath = transcriptName.startsWith(\"/\")\n ? transcriptName\n : join(absProject, transcriptName);\n if (!existsSync(absPath) || !statSync(absPath).isFile()) {\n return err(`transcript \"${transcriptName}\" not found in ${absProject}`);\n }\n chosen = { absPath, name: transcriptName };\n } else {\n const candidates = discoverTranscripts(absProject);\n if (candidates.length === 0) {\n return err(`no transcript found in ${absProject} (looked for transcript.json and transcripts/*.json)`);\n }\n if (candidates.length > 1) {\n return err(\n `multiple transcripts present in ${absProject}; pass transcriptName explicitly. ` +\n `Candidates: ${candidates.map((c) => c.name).join(\", \")}`,\n );\n }\n chosen = candidates[0];\n }\n\n let rawTranscript: VideoTranscript;\n try {\n rawTranscript = JSON.parse(readFileSync(chosen.absPath, \"utf-8\")) as VideoTranscript;\n } catch (e) {\n return err(`failed to parse transcript at ${chosen.absPath}: ${(e as Error).message}`);\n }\n\n const cutsPath = join(absProject, \"cuts.json\");\n if (!existsSync(cutsPath)) {\n // No cuts.json — raw transcript is effective.\n return ok({\n effective: rawTranscript as unknown as Record<string, unknown>,\n source: {\n transcriptName: chosen.name,\n cutsApplied: 0,\n totalCutDurationS: 0,\n },\n });\n }\n\n let rawCuts: { cuts?: CutEntry[] };\n try {\n rawCuts = JSON.parse(readFileSync(cutsPath, \"utf-8\"));\n } catch (e) {\n return err(`failed to parse cuts at ${cutsPath}: ${(e as Error).message}`);\n }\n const cuts = rawCuts.cuts ?? [];\n\n if (cuts.length === 0) {\n return ok({\n effective: rawTranscript as unknown as Record<string, unknown>,\n source: {\n transcriptName: chosen.name,\n cutsApplied: 0,\n totalCutDurationS: 0,\n },\n });\n }\n\n const effective = applyCuts(rawTranscript, cuts, {\n transcriptName: chosen.name,\n cutsHash: hashCuts(cuts),\n derivedAt: new Date().toISOString(),\n });\n\n return ok({\n effective: effective as unknown as Record<string, unknown>,\n source: {\n transcriptName: chosen.name,\n cutsApplied: effective.derived_from?.cutsApplied ?? cuts.length,\n totalCutDurationS: effective.derived_from?.totalCutDurationS ?? 0,\n },\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Media notes (sidecar `<file>.notes.md`) tools.\n//\n// Two tools:\n// atelier_get_media_notes — pure read of a media file's notes sidecar.\n// atelier_write_media_note — append/replace an author's section.\n//\n// Dependency note: the canonical readMediaNotes/appendNoteSection helpers\n// live in the CLI package (`packages/cli/src/lib/media-notes.ts`). MCP does\n// NOT depend on CLI (cycle), so the read+upsert logic is re-implemented here\n// against @a-company/atelier-schema (MediaNotesFrontmatterSchema +\n// MEDIA_NOTES_HEADINGS) and the `yaml` package. This mirrors the existing\n// duplication of recipe overlay logic in recipes.ts.\n//\n// Both tools are scoped via projectDir + filename so callers cannot read or\n// write outside the project's media/ subtree. The filename argument is\n// basename-only (no path separators) — defense in depth against a malformed\n// path argument escaping the media/ root.\n\nimport { existsSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport {\n MediaNotesAuthorSchema,\n MediaNotesFrontmatterSchema,\n MEDIA_NOTES_HEADINGS,\n type MediaNotes,\n type MediaNotesAuthor,\n type MediaNotesFrontmatter,\n} from \"@a-company/atelier-schema\";\nimport type { DocumentStore } from \"../store.js\";\n\n// ─── Envelope helpers (mirror mind-map.ts) ────────────────────────\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }],\n isError: true as const,\n };\n}\n\n// ─── Path resolution (basename-only guard) ────────────────────────\n\nconst MEDIA_NOTES_SUFFIX = \".notes.md\";\n\n/**\n * Resolve `<projectDir>/media/<filename>` and its sidecar. Refuses any\n * filename that includes a path separator — callers are expected to pass a\n * bare basename, never a path. Returns the absolute paths.\n */\nfunction resolveMediaPaths(\n projectDir: string,\n filename: string,\n): { project: string; mediaPath: string; notesPath: string } | { error: string } {\n const absProject = resolve(projectDir);\n if (!existsSync(absProject) || !statSync(absProject).isDirectory()) {\n return { error: `projectDir \"${absProject}\" is not a directory` };\n }\n if (filename.includes(\"/\") || filename.includes(\"\\\\\") || filename === \"..\") {\n return { error: `filename must be a bare basename (got \"${filename}\")` };\n }\n const mediaPath = join(absProject, \"media\", filename);\n const notesPath = `${mediaPath}${MEDIA_NOTES_SUFFIX}`;\n return { project: absProject, mediaPath, notesPath };\n}\n\n// ─── Notes read/write (duplicated from cli/media-notes.ts) ────────\n\ninterface FrontmatterSplit {\n frontmatter: string;\n body: string;\n}\n\nfunction splitFrontmatter(raw: string): FrontmatterSplit | null {\n const trimmed = raw.replace(/^/, \"\");\n if (!trimmed.startsWith(\"---\")) return null;\n const lines = trimmed.split(/\\r?\\n/);\n if (lines[0].trim() !== \"---\") return null;\n let closeIdx = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === \"---\") {\n closeIdx = i;\n break;\n }\n }\n if (closeIdx === -1) return null;\n return {\n frontmatter: lines.slice(1, closeIdx).join(\"\\n\"),\n body: lines.slice(closeIdx + 1).join(\"\\n\").replace(/^\\n+/, \"\"),\n };\n}\n\nfunction readNotesFile(notesPath: string): MediaNotes | null {\n if (!existsSync(notesPath)) return null;\n const raw = readFileSync(notesPath, \"utf-8\");\n const split = splitFrontmatter(raw);\n if (split === null) return null;\n let parsed: unknown;\n try {\n parsed = parseYaml(split.frontmatter);\n } catch {\n return null;\n }\n const validated = MediaNotesFrontmatterSchema.safeParse(parsed);\n if (!validated.success) return null;\n return { frontmatter: validated.data, body: split.body };\n}\n\nfunction writeNotesFile(notesPath: string, notes: MediaNotes): void {\n const yamlText = stringifyYaml(notes.frontmatter);\n const body = notes.body.endsWith(\"\\n\") ? notes.body : `${notes.body}\\n`;\n writeFileSync(notesPath, `---\\n${yamlText}---\\n\\n${body}`, \"utf-8\");\n}\n\nfunction upsertSection(body: string, heading: string, newBlock: string): string {\n const lines = body.split(/\\r?\\n/);\n let startIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].trim() === heading) {\n startIdx = i;\n break;\n }\n }\n if (startIdx === -1) {\n const existing = body.trimEnd();\n return existing.length > 0 ? `${existing}\\n\\n${newBlock.trimEnd()}\\n` : `${newBlock.trimEnd()}\\n`;\n }\n let endIdx = lines.length;\n for (let i = startIdx + 1; i < lines.length; i++) {\n if (lines[i].startsWith(\"## \")) {\n endIdx = i;\n break;\n }\n }\n const before = lines.slice(0, startIdx);\n const after = lines.slice(endIdx);\n const replacement = newBlock.split(/\\r?\\n/);\n while (replacement.length > 0 && replacement[replacement.length - 1] === \"\") {\n replacement.pop();\n }\n const joined = [...before, ...replacement];\n if (after.length > 0 && after[0].startsWith(\"## \")) {\n joined.push(\"\");\n }\n joined.push(...after);\n return joined.join(\"\\n\").replace(/\\n+$/, \"\\n\");\n}\n\n// ─── Tool registration ───────────────────────────────────────────\n\nexport function register(server: McpServer, _store: DocumentStore): void {\n // _store unused — both tools work against the filesystem only.\n\n server.tool(\n \"atelier_get_media_notes\",\n \"Read the sidecar notes file for a media entry — <projectDir>/media/<filename>.notes.md. \" +\n \"Returns the parsed frontmatter (file, added, added_by, tags, optional constraints) \" +\n \"plus the Markdown body. Returns an error envelope when the notes file is absent or \" +\n \"malformed; pure read, does not touch the document store.\",\n {\n projectDir: z.string().describe(\"Absolute or cwd-relative project root\"),\n filename: z.string().describe(\"Bare basename of the media file (e.g. 'b-roll-laptop.mp4')\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ projectDir, filename }) => {\n const paths = resolveMediaPaths(projectDir, filename);\n if (\"error\" in paths) return err(paths.error);\n\n if (!existsSync(paths.notesPath)) {\n return err(`notes file not found: ${paths.notesPath}`);\n }\n const notes = readNotesFile(paths.notesPath);\n if (notes === null) {\n return err(`notes file at ${paths.notesPath} is malformed (frontmatter parse / schema validation failed)`);\n }\n return ok({\n path: paths.notesPath,\n frontmatter: notes.frontmatter as unknown as Record<string, unknown>,\n body: notes.body,\n });\n },\n );\n\n server.tool(\n \"atelier_write_media_note\",\n \"Append or replace an author's section in a media file's sidecar notes. \" +\n \"Section boundaries are detected by the per-author sentinel headings \" +\n \"(## Lux notes / Quill notes / Iris notes / Creator notes); a second call with the \" +\n \"same author replaces the prior section rather than duplicating. The notes file \" +\n \"MUST exist already (scaffold via `atelier media ingest` or `atelier media note`). \" +\n \"Mutates disk; the calling agent is tagged via the `author` argument.\",\n {\n projectDir: z.string().describe(\"Absolute or cwd-relative project root\"),\n filename: z.string().describe(\"Bare basename of the media file\"),\n author: MediaNotesAuthorSchema.describe(\"Section owner: lux | quill | iris | creator\"),\n section: z.string().describe(\"Markdown body for the section (heading is added automatically)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ projectDir, filename, author, section }) => {\n const paths = resolveMediaPaths(projectDir, filename);\n if (\"error\" in paths) return err(paths.error);\n\n if (!existsSync(paths.notesPath)) {\n return err(\n `notes file not found: ${paths.notesPath} — scaffold via \\`atelier media ingest\\` or \\`atelier media note\\` first`,\n );\n }\n const existing = readNotesFile(paths.notesPath);\n if (existing === null) {\n return err(\n `notes file at ${paths.notesPath} is malformed — refusing to write into a file with unparseable frontmatter`,\n );\n }\n\n const typedAuthor = author as MediaNotesAuthor;\n const heading = MEDIA_NOTES_HEADINGS[typedAuthor];\n const trimmed = section.trim();\n const newBlock = `${heading}\\n${trimmed}\\n`;\n\n // Did the section already exist? Used to report action: replaced|appended.\n const hasExistingSection = existing.body\n .split(/\\r?\\n/)\n .some((l) => l.trim() === heading);\n\n const updatedBody = upsertSection(existing.body, heading, newBlock);\n const updated: MediaNotes = { frontmatter: existing.frontmatter as MediaNotesFrontmatter, body: updatedBody };\n writeNotesFile(paths.notesPath, updated);\n\n return ok({\n path: paths.notesPath,\n action: hasExistingSection ? \"replaced\" : \"appended\",\n author: typedAuthor,\n });\n },\n );\n}\n","// @a-company/atelier-mcp — Clip + slide authoring tools (v1.0 Slice A)\n//\n// Six tools that give programmatic clip authoring on disk-backed projects:\n// - atelier_add_clip — register an asset + clip layer on a track\n// - atelier_move_clip — shift a clip's composition-time startFrame\n// - atelier_trim_clip — adjust a clip's sourceOffset / sourceEnd\n// - atelier_remove_clip — drop a clip and its parented captions\n// - atelier_transcribe_clip — run transcription and (re)build clip captions\n// - atelier_move_slide — reorder a carousel project's slides array\n//\n// All take `documentId + projectDir` and round-trip through disk:\n// read project.atelier → mutate → write JSON → reload into the store.\n// Mutations land via store.set(documentId, doc, \"llm\") so the live bridge\n// re-broadcasts to attached studio instances.\n//\n// Dependency note: timeline primitives (track + clip helpers, caption build,\n// ffprobe wrap) are duplicated under packages/mcp/src/lib/timeline-ops.ts to\n// avoid a cli↔mcp cycle — see that file's header for the rationale.\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { basename, extname, isAbsolute, join, resolve } from \"node:path\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n AtelierDocument,\n AudioVisual,\n Layer,\n SlideRef,\n State,\n VideoTranscript,\n VideoVisual,\n} from \"@a-company/atelier-types\";\nimport type { DocumentStore } from \"../store.js\";\nimport {\n AUDIO_TRACK_ID,\n VIDEO_TRACK_ID,\n ensureClipLayer,\n probeDuration as defaultProbeDuration,\n rebuildClipCaptions,\n recomputeTimeline,\n slugifyBasename,\n} from \"../lib/timeline-ops.js\";\n\n// ─── Response envelopes (mirror assets.ts) ────────────────────────\n\nfunction ok(data: Record<string, unknown>) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...data }) }] };\n}\n\nfunction err(message: string) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }],\n isError: true as const,\n };\n}\n\n// ─── Disk round-trip helpers ──────────────────────────────────────\n\ninterface LoadedDoc {\n doc: AtelierDocument;\n compositionPath: string;\n}\n\nfunction loadDocFromDisk(projectDir: string): LoadedDoc | { error: string } {\n const absProject = resolve(projectDir);\n const compositionPath = join(absProject, \"project.atelier\");\n if (!existsSync(compositionPath)) {\n return { error: `project.atelier not found at ${compositionPath}` };\n }\n let raw: string;\n try {\n raw = readFileSync(compositionPath, \"utf-8\");\n } catch (e) {\n return { error: `failed to read ${compositionPath}: ${(e as Error).message}` };\n }\n let doc: AtelierDocument;\n try {\n doc = JSON.parse(raw) as AtelierDocument;\n } catch (e) {\n return { error: `failed to parse ${compositionPath}: ${(e as Error).message}` };\n }\n return { doc, compositionPath };\n}\n\nfunction persistDoc(\n store: DocumentStore,\n documentId: string,\n doc: AtelierDocument,\n compositionPath: string,\n): void {\n writeFileSync(compositionPath, JSON.stringify(doc, null, 2), \"utf-8\");\n if (store.has(documentId)) {\n store.set(documentId, doc, \"llm\");\n } else {\n store.create(doc, documentId, \"llm\");\n }\n}\n\n/**\n * Resolve a media source to a project-relative `media/<basename>` string +\n * absolute path. Accepts absolute paths anywhere on disk OR project-relative\n * paths. The stored `src` is always relative to projectDir when the file\n * lives under projectDir, otherwise the basename.\n */\nfunction canonicalSourceName(source: string, projectDir: string): { srcRef: string; absPath: string } {\n const absProject = resolve(projectDir);\n const abs = isAbsolute(source) ? source : resolve(absProject, source);\n if (abs.startsWith(`${absProject}/`)) {\n return { srcRef: abs.slice(absProject.length + 1), absPath: abs };\n }\n return { srcRef: basename(abs), absPath: abs };\n}\n\n// ─── Endpoint-frame computation for move/trim ─────────────────────\n\nfunction clipEndFrame(visual: VideoVisual | AudioVisual, fps: number): number {\n const start = visual.startFrame ?? 0;\n const offset = visual.sourceOffset ?? 0;\n const end = visual.sourceEnd ?? offset;\n const durFrames = Math.max(0, Math.round((end - offset) * fps));\n return start + durFrames;\n}\n\n// ─── Transcribe injection point ───────────────────────────────────\n\n/**\n * Tool-input fn for transcribing a media file. Mirrors composeVideoProject's\n * `transcribeFn` test-injection pattern. In tests this is stubbed to return a\n * pre-baked transcript; in production a studio host wires this to the real\n * whisper-backed pipeline.\n */\nexport type TranscribeClipFn = (\n args: { projectDir: string; mediaBasename: string; model?: string },\n) => Promise<{ transcript: VideoTranscript; transcriptPath: string }>;\n\n// NOTE: these are module-level globals. Safe under vitest's default worker\n// isolation (one process per test file) and under the typical single-process\n// stdio server. Running tests with --no-isolate, or instantiating two\n// MCP servers in the same process that need different stubs, would race —\n// add per-call options to the tool inputs if that becomes a constraint.\nlet injectedTranscribeFn: TranscribeClipFn | undefined;\nlet injectedProbeDurationFn: ((sourcePath: string) => Promise<number>) | undefined;\n\n/** Test hook — install a transcribe stub used when a per-call fn isn't passed. */\nexport function __setTranscribeClipFn(fn: TranscribeClipFn | undefined): void {\n injectedTranscribeFn = fn;\n}\n\n/** Test hook — install a probeDuration stub used when a per-call fn isn't passed. */\nexport function __setProbeDurationFn(fn: ((sourcePath: string) => Promise<number>) | undefined): void {\n injectedProbeDurationFn = fn;\n}\n\n// ─── Tool registrations ───────────────────────────────────────────\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── atelier_add_clip ────────────────────────────────────────\n server.tool(\n \"atelier_add_clip\",\n \"Register a media source as a clip layer on a video or audio track. Idempotent: \" +\n \"re-running with the same source preserves the existing clip's placement and \" +\n \"applies only explicitly-passed startFrame/sourceOffset/sourceEnd overrides.\",\n {\n documentId: z.string().describe(\"In-memory document ID to reload after disk write\"),\n projectDir: z.string().describe(\"Absolute path to the project root (contains project.atelier)\"),\n source: z.string().describe(\"Absolute media path OR project-relative path (e.g. media/clip.mp4)\"),\n kind: z.enum([\"video\", \"audio\"]).optional().describe(\"Clip kind (default: video)\"),\n trackId: z.string().optional().describe(\"Track layer id (default: track-video-1 / track-audio-1)\"),\n startFrame: z.number().int().nonnegative().optional().describe(\"Composition-frame start (default: end-of-track)\"),\n sourceOffset: z.number().nonnegative().optional().describe(\"Seconds into source to begin from\"),\n sourceEnd: z.number().positive().optional().describe(\"Seconds into source to stop at\"),\n layerIdHint: z.string().optional().describe(\"Explicit layer id override (default: clip-<slug> or aud-<slug>)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, projectDir, source, kind, trackId, startFrame, sourceOffset, sourceEnd, layerIdHint }) => {\n const loaded = loadDocFromDisk(projectDir);\n if (\"error\" in loaded) return err(loaded.error);\n let { doc } = loaded;\n const { compositionPath } = loaded;\n\n const clipKind: \"video\" | \"audio\" = kind ?? \"video\";\n const resolvedTrackId = trackId ?? (clipKind === \"video\" ? VIDEO_TRACK_ID : AUDIO_TRACK_ID);\n\n const { srcRef, absPath } = canonicalSourceName(source, projectDir);\n const slug = slugifyBasename(srcRef);\n if (!slug) return err(`cannot derive a slug from source \"${source}\"`);\n\n const layerId = layerIdHint ?? (clipKind === \"video\" ? `clip-${slug}` : `aud-${slug}`);\n\n // Probe duration; ffprobe failures fall back to 0 so the clip still lands\n // (mirrors composeVideoProject's fallback contract).\n const probeFn = injectedProbeDurationFn ?? defaultProbeDuration;\n let clipDurationSeconds = 0;\n try {\n clipDurationSeconds = await probeFn(absPath);\n } catch {\n clipDurationSeconds = 0;\n }\n const fps = doc.canvas.fps;\n const clipDurationFrames = Math.max(1, Math.round(clipDurationSeconds * fps));\n\n // Idempotence: if the layer already exists, apply ONLY explicit overrides.\n const existing = doc.layers.find((l) => l.id === layerId);\n let addedLayer = false;\n if (existing) {\n if (existing.visual.type !== clipKind) {\n return err(`layer \"${layerId}\" exists but is type \"${existing.visual.type}\", not \"${clipKind}\"`);\n }\n const v = existing.visual as VideoVisual | AudioVisual;\n const patched = { ...v };\n if (startFrame !== undefined) patched.startFrame = startFrame;\n if (sourceOffset !== undefined) patched.sourceOffset = sourceOffset;\n if (sourceEnd !== undefined) patched.sourceEnd = sourceEnd;\n doc = {\n ...doc,\n layers: doc.layers.map((l) => (l.id === layerId ? { ...l, visual: patched } : l)),\n };\n } else {\n const ensured = ensureClipLayer(doc, {\n clipLayerId: layerId,\n trackId: resolvedTrackId,\n sourceName: srcRef,\n clipDurationSeconds,\n clipDurationFrames,\n kind: clipKind,\n ...(startFrame !== undefined ? { startFrame } : {}),\n ...(sourceOffset !== undefined ? { sourceOffset } : {}),\n ...(sourceEnd !== undefined ? { sourceEnd } : {}),\n });\n doc = ensured.doc;\n addedLayer = ensured.addedLayer;\n }\n\n doc = recomputeTimeline(doc);\n\n const final = doc.layers.find((l) => l.id === layerId);\n if (!final) return err(`internal: layer \"${layerId}\" missing after ensureClipLayer`);\n const visual = final.visual as VideoVisual | AudioVisual;\n const resolvedStart = visual.startFrame ?? 0;\n const resolvedEnd = clipEndFrame(visual, fps);\n\n persistDoc(store, documentId, doc, compositionPath);\n\n return ok({\n layerId,\n trackId: resolvedTrackId,\n startFrame: resolvedStart,\n endFrame: resolvedEnd,\n addedLayer,\n });\n },\n );\n\n // ── atelier_move_clip ───────────────────────────────────────\n server.tool(\n \"atelier_move_clip\",\n \"Shift a clip's composition-frame start. Caption layers parented to the clip stay \" +\n \"aligned automatically (renderer uses clip-local time). Recomputes the timeline.\",\n {\n documentId: z.string().describe(\"In-memory document ID to reload after disk write\"),\n projectDir: z.string().describe(\"Absolute path to the project root\"),\n layerId: z.string().describe(\"Layer id of the clip to move\"),\n newStartFrame: z.number().int().nonnegative().describe(\"New composition-frame start\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, projectDir, layerId, newStartFrame }) => {\n const loaded = loadDocFromDisk(projectDir);\n if (\"error\" in loaded) return err(loaded.error);\n let { doc } = loaded;\n const { compositionPath } = loaded;\n\n const layer = doc.layers.find((l) => l.id === layerId);\n if (!layer) return err(`clip layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"video\" && layer.visual.type !== \"audio\") {\n return err(`layer \"${layerId}\" is type \"${layer.visual.type}\", not a clip`);\n }\n\n const oldVisual = layer.visual as VideoVisual | AudioVisual;\n const oldStartFrame = oldVisual.startFrame ?? 0;\n const newVisual = { ...oldVisual, startFrame: newStartFrame };\n doc = {\n ...doc,\n layers: doc.layers.map((l) => (l.id === layerId ? { ...l, visual: newVisual } : l)),\n };\n doc = recomputeTimeline(doc);\n\n const endFrame = clipEndFrame(newVisual, doc.canvas.fps);\n persistDoc(store, documentId, doc, compositionPath);\n\n return ok({ layerId, oldStartFrame, newStartFrame, endFrame });\n },\n );\n\n // ── atelier_trim_clip ───────────────────────────────────────\n server.tool(\n \"atelier_trim_clip\",\n \"Adjust a clip's sourceOffset / sourceEnd (in seconds). Captions outside the new \" +\n \"effective range are not auto-pruned — the renderer skips out-of-range deltas.\",\n {\n documentId: z.string().describe(\"In-memory document ID to reload after disk write\"),\n projectDir: z.string().describe(\"Absolute path to the project root\"),\n layerId: z.string().describe(\"Layer id of the clip to trim\"),\n sourceOffset: z.number().nonnegative().optional().describe(\"New seconds-into-source start\"),\n sourceEnd: z.number().positive().optional().describe(\"New seconds-into-source end\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, projectDir, layerId, sourceOffset, sourceEnd }) => {\n if (sourceOffset === undefined && sourceEnd === undefined) {\n return err(\"at least one of sourceOffset / sourceEnd must be provided\");\n }\n const loaded = loadDocFromDisk(projectDir);\n if (\"error\" in loaded) return err(loaded.error);\n let { doc } = loaded;\n const { compositionPath } = loaded;\n\n const layer = doc.layers.find((l) => l.id === layerId);\n if (!layer) return err(`clip layer \"${layerId}\" not found`);\n if (layer.visual.type !== \"video\" && layer.visual.type !== \"audio\") {\n return err(`layer \"${layerId}\" is type \"${layer.visual.type}\", not a clip`);\n }\n\n const oldVisual = layer.visual as VideoVisual | AudioVisual;\n const newVisual: VideoVisual | AudioVisual = { ...oldVisual };\n if (sourceOffset !== undefined) newVisual.sourceOffset = sourceOffset;\n if (sourceEnd !== undefined) newVisual.sourceEnd = sourceEnd;\n doc = {\n ...doc,\n layers: doc.layers.map((l) => (l.id === layerId ? { ...l, visual: newVisual } : l)),\n };\n doc = recomputeTimeline(doc);\n\n persistDoc(store, documentId, doc, compositionPath);\n\n return ok({\n layerId,\n sourceOffset: newVisual.sourceOffset ?? 0,\n sourceEnd: newVisual.sourceEnd,\n startFrame: newVisual.startFrame ?? 0,\n endFrame: clipEndFrame(newVisual, doc.canvas.fps),\n });\n },\n );\n\n // ── atelier_remove_clip ────────────────────────────────────\n server.tool(\n \"atelier_remove_clip\",\n \"Remove a clip layer plus all transitively-parented descendants (e.g. its caption \" +\n \"layers) and any deltas referencing them. Refuses to remove a track group layer.\",\n {\n documentId: z.string().describe(\"In-memory document ID to reload after disk write\"),\n projectDir: z.string().describe(\"Absolute path to the project root\"),\n layerId: z.string().describe(\"Layer id of the clip to remove\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ documentId, projectDir, layerId }) => {\n const loaded = loadDocFromDisk(projectDir);\n if (\"error\" in loaded) return err(loaded.error);\n let { doc } = loaded;\n const { compositionPath } = loaded;\n\n const layer = doc.layers.find((l) => l.id === layerId);\n if (!layer) return err(`layer \"${layerId}\" not found`);\n if ((layer.tags ?? []).includes(\"track\")) {\n return err(\"Cannot remove track group; use atelier_remove_track (not implemented in v1)\");\n }\n\n // BFS transitive descendants.\n const toRemove = new Set<string>([layerId]);\n let grew = true;\n while (grew) {\n grew = false;\n for (const l of doc.layers) {\n if (toRemove.has(l.id)) continue;\n if (l.parentId && toRemove.has(l.parentId)) {\n toRemove.add(l.id);\n grew = true;\n }\n }\n }\n\n const remainingLayers: Layer[] = doc.layers.filter((l) => !toRemove.has(l.id));\n const newStates: Record<string, State> = {};\n for (const [name, st] of Object.entries(doc.states)) {\n newStates[name] = {\n ...st,\n deltas: st.deltas.filter((d) => !toRemove.has(d.layer)),\n };\n }\n const assets = { ...(doc.assets ?? {}) };\n for (const id of toRemove) delete assets[id];\n\n // Drop the assets field entirely when empty to match the existing\n // convention (compose-video-project never writes an empty assets map).\n if (Object.keys(assets).length === 0) {\n const { assets: _omit, ...rest } = doc;\n void _omit;\n doc = { ...(rest as AtelierDocument), layers: remainingLayers, states: newStates };\n } else {\n doc = { ...doc, layers: remainingLayers, states: newStates, assets };\n }\n doc = recomputeTimeline(doc);\n\n persistDoc(store, documentId, doc, compositionPath);\n\n return ok({\n layerId,\n removedLayerIds: Array.from(toRemove),\n removedCount: toRemove.size,\n });\n },\n );\n\n // ── atelier_transcribe_clip ────────────────────────────────\n server.tool(\n \"atelier_transcribe_clip\",\n \"Run transcription on a clip's source media and (re)build parented caption layers. \" +\n \"Audio-layer captions are not supported in v1. Requires a transcribeFn injected via \" +\n \"__setTranscribeClipFn (tests) or a pre-existing transcript at \" +\n \"<projectDir>/transcripts/<stem>.json.\",\n {\n documentId: z.string().describe(\"In-memory document ID to reload after disk write\"),\n projectDir: z.string().describe(\"Absolute path to the project root\"),\n layerId: z.string().describe(\"Video clip layer id\"),\n model: z.string().optional().describe(\"Whisper model selection forwarded to the injected transcribeFn\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, projectDir, layerId, model }) => {\n const loaded = loadDocFromDisk(projectDir);\n if (\"error\" in loaded) return err(loaded.error);\n let { doc } = loaded;\n const { compositionPath } = loaded;\n\n const layer = doc.layers.find((l) => l.id === layerId);\n if (!layer) return err(`clip layer \"${layerId}\" not found`);\n if (layer.visual.type === \"audio\") {\n return err(\"audio layer captions are not supported in v1\");\n }\n if (layer.visual.type !== \"video\") {\n return err(`layer \"${layerId}\" is type \"${layer.visual.type}\", not a video clip`);\n }\n\n const v = layer.visual as VideoVisual;\n const srcRef = v.src;\n if (!srcRef) return err(`video layer \"${layerId}\" has no src`);\n const mediaBasename = basename(srcRef);\n\n // Production wiring: prefer an injected transcribeFn (studio host). Tests\n // also inject via __setTranscribeClipFn. Fallback: read an existing\n // transcript mirror from <projectDir>/transcripts/<stem>.json.\n let transcript: VideoTranscript | undefined;\n let transcriptPath: string | undefined;\n if (injectedTranscribeFn) {\n const result = await injectedTranscribeFn({\n projectDir,\n mediaBasename,\n ...(model !== undefined ? { model } : {}),\n });\n transcript = result.transcript;\n transcriptPath = result.transcriptPath;\n } else {\n const stem = stripExt(mediaBasename);\n const candidate = join(resolve(projectDir), \"transcripts\", `${stem}.json`);\n if (!existsSync(candidate)) {\n return err(\n `no transcribeFn injected and no transcript mirror at ${candidate}. ` +\n \"Install a host-provided transcribeFn via __setTranscribeClipFn or pre-write the transcript.\",\n );\n }\n try {\n transcript = JSON.parse(readFileSync(candidate, \"utf-8\")) as VideoTranscript;\n transcriptPath = candidate;\n } catch (e) {\n return err(`failed to read transcript at ${candidate}: ${(e as Error).message}`);\n }\n }\n\n if (!transcript) return err(\"transcribeFn returned no transcript\");\n\n doc = rebuildClipCaptions(doc, layerId, transcript, doc.canvas);\n doc = recomputeTimeline(doc);\n\n const captionCount = doc.layers.filter(\n (l) => l.parentId === layerId && (l.tags ?? []).includes(\"caption\"),\n ).length;\n\n persistDoc(store, documentId, doc, compositionPath);\n\n return ok({\n layerId,\n transcriptPath: transcriptPath ?? null,\n captionCount,\n });\n },\n );\n\n // ── atelier_move_slide ─────────────────────────────────────\n server.tool(\n \"atelier_move_slide\",\n \"Reorder a carousel project's slides[] array. Refuses on non-carousel projects.\",\n {\n documentId: z.string().describe(\"In-memory document ID to reload after disk write\"),\n projectDir: z.string().describe(\"Absolute path to the project root\"),\n fromIndex: z.number().int().nonnegative().describe(\"Current index in slides[]\"),\n toIndex: z.number().int().nonnegative().describe(\"Target index in slides[]\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, projectDir, fromIndex, toIndex }) => {\n const loaded = loadDocFromDisk(projectDir);\n if (\"error\" in loaded) return err(loaded.error);\n let { doc } = loaded;\n const { compositionPath } = loaded;\n\n if (doc.kind !== \"carousel\") {\n return err(`project kind is \"${doc.kind ?? \"video\"}\", not \"carousel\"`);\n }\n const slides: SlideRef[] = [...(doc.slides ?? [])];\n if (fromIndex >= slides.length) {\n return err(`fromIndex ${fromIndex} out of bounds (slides.length=${slides.length})`);\n }\n if (toIndex >= slides.length) {\n return err(`toIndex ${toIndex} out of bounds (slides.length=${slides.length})`);\n }\n\n const [moved] = slides.splice(fromIndex, 1);\n slides.splice(toIndex, 0, moved);\n doc = { ...doc, slides };\n\n persistDoc(store, documentId, doc, compositionPath);\n\n return ok({ slides });\n },\n );\n}\n\nfunction stripExt(name: string): string {\n const ext = extname(name);\n return ext ? name.slice(0, -ext.length) : name;\n}\n","// #mcp-timeline-ops — clip + caption timeline helpers for the MCP clip tools.\n//\n// **Intentional duplication** of `packages/cli/src/lib/timeline-ops.ts` plus\n// the transitively-required slugifier / caption-builder / phrase-grouper.\n// MCP cannot import from `@a-company/atelier` (the CLI package) because\n// `cli → mcp` already runs in the dep graph — re-importing back would close\n// the cycle. The same duplication convention is used by recipes.ts /\n// overlays.ts / effective-transcript.ts / media-notes.ts (all carry a\n// \"re-implemented from cli/...\" header comment).\n//\n// If the canonical helpers in cli/lib/timeline-ops.ts change semantics, this\n// file MUST be kept in sync — there is no shared package between mcp and cli\n// for these primitives in v1.0. Lifting timeline-ops into a shared package\n// (e.g. `atelier-timeline`) is tracked as a Unit-0.5 follow-up.\n//\n// Track convention (matches cli/timeline-ops):\n// - track-video-1, track-audio-1 are the stable ids for the primary video\n// and primary audio Group layers. Lazy-created by `ensureTrackLayer`.\n\nimport { basename, extname } from \"node:path\";\nimport { spawn } from \"node:child_process\";\n\nimport type {\n AtelierDocument,\n Asset,\n AudioVisual,\n Delta,\n Layer,\n State,\n Timeline,\n TimelineClip,\n TimelineTrack,\n TranscriptWord,\n VideoTranscript,\n VideoVisual,\n} from \"@a-company/atelier-types\";\n\n/** Stable id for the lazily-created primary video track group layer. */\nexport const VIDEO_TRACK_ID = \"track-video-1\";\n\n/** Stable id for the lazily-created primary audio track group layer. */\nexport const AUDIO_TRACK_ID = \"track-audio-1\";\n\n// ─── Slugifier (duplicated from cli/compose-video-project.ts) ─────\n\n/**\n * Slug an arbitrary basename into a kebab-case identifier suitable for layer /\n * asset ids: lowercase, strip extension, replace runs of non-[a-z0-9] with `-`,\n * trim leading/trailing dashes. e.g. `IMG_7346.MOV` → `img-7346`.\n */\nexport function slugifyBasename(name: string): string {\n const base = basename(name);\n const stem = stripExt(base);\n const lower = stem.toLowerCase();\n const replaced = lower.replace(/[^a-z0-9]+/g, \"-\");\n return replaced.replace(/^-+|-+$/g, \"\");\n}\n\nfunction stripExt(name: string): string {\n const ext = extname(name);\n return ext ? name.slice(0, -ext.length) : name;\n}\n\n// ─── Track + clip helpers (duplicated from cli/timeline-ops.ts) ───\n\nexport function endOfTrackFrame(\n layers: Layer[],\n trackId: string,\n fps: number,\n): number {\n let maxEnd = 0;\n for (const layer of layers) {\n if (layer.parentId !== trackId) continue;\n const v = layer.visual;\n if (v.type !== \"video\" && v.type !== \"audio\") continue;\n const tv = v as VideoVisual | AudioVisual;\n const start = tv.startFrame ?? 0;\n const offset = tv.sourceOffset ?? 0;\n const end = tv.sourceEnd;\n if (end === undefined) continue;\n const durFrames = Math.max(0, Math.round((end - offset) * fps));\n const layerEnd = start + durFrames;\n if (layerEnd > maxEnd) maxEnd = layerEnd;\n }\n return maxEnd;\n}\n\n/** Lazy-create a track Group layer if missing. Idempotent. */\nexport function ensureTrackLayer(\n doc: AtelierDocument,\n trackId: string,\n kind: \"video\" | \"audio\",\n): { doc: AtelierDocument; created: boolean } {\n const exists = doc.layers.some((l) => l.id === trackId);\n if (exists) return { doc, created: false };\n\n const trackLayer: Layer = {\n id: trackId,\n tags: [\"track\", kind],\n description: kind === \"video\" ? \"Video track 1\" : \"Audio track 1\",\n visual: { type: \"group\" },\n frame: { x: 0, y: 0 },\n bounds: { width: doc.canvas.width, height: doc.canvas.height },\n };\n return {\n doc: { ...doc, layers: [trackLayer, ...doc.layers] },\n created: true,\n };\n}\n\n/** Args for ensureClipLayer — supports both video and audio clips. */\nexport interface EnsureClipArgs {\n clipLayerId: string;\n trackId: string;\n sourceName: string;\n clipDurationSeconds: number;\n clipDurationFrames: number;\n kind: \"video\" | \"audio\";\n startFrame?: number;\n sourceOffset?: number;\n sourceEnd?: number;\n}\n\n/**\n * Idempotent clip-layer placement, generalized for video AND audio.\n * Mirror of cli/timeline-ops.ts:ensureClipLayer.\n */\nexport function ensureClipLayer(\n doc: AtelierDocument,\n args: EnsureClipArgs,\n): { doc: AtelierDocument; addedLayer: boolean; clipLayerId: string } {\n const existing = doc.layers.find((l) => l.id === args.clipLayerId);\n if (existing) {\n return { doc, addedLayer: false, clipLayerId: args.clipLayerId };\n }\n\n const ensured = ensureTrackLayer(doc, args.trackId, args.kind);\n const working = ensured.doc;\n\n const startFrame =\n args.startFrame !== undefined\n ? args.startFrame\n : endOfTrackFrame(working.layers, args.trackId, working.canvas.fps);\n\n const sourceOffset = args.sourceOffset ?? 0;\n const sourceEnd = args.sourceEnd ?? args.clipDurationSeconds;\n\n const newAsset: Asset = {\n type: args.kind === \"video\" ? \"video\" : \"audio\",\n src: args.sourceName,\n description: `Source: ${args.sourceName}`,\n };\n const assets: Record<string, Asset> = {\n ...(working.assets ?? {}),\n [args.clipLayerId]: newAsset,\n };\n\n let newClip: Layer;\n if (args.kind === \"video\") {\n const visual: VideoVisual = {\n type: \"video\",\n assetId: args.clipLayerId,\n src: args.sourceName,\n startFrame,\n sourceOffset,\n sourceEnd,\n playbackRate: 1.0,\n objectFit: \"contain\",\n };\n newClip = {\n id: args.clipLayerId,\n parentId: args.trackId,\n visual,\n frame: { x: 0, y: 0 },\n bounds: { width: working.canvas.width, height: working.canvas.height },\n };\n } else {\n const visual: AudioVisual = {\n type: \"audio\",\n assetId: args.clipLayerId,\n src: args.sourceName,\n startFrame,\n sourceOffset,\n sourceEnd,\n };\n newClip = {\n id: args.clipLayerId,\n parentId: args.trackId,\n visual,\n frame: { x: 0, y: 0 },\n bounds: { width: 0, height: 0 },\n };\n }\n\n return {\n doc: {\n ...working,\n assets,\n layers: [...working.layers, newClip],\n },\n addedLayer: true,\n clipLayerId: args.clipLayerId,\n };\n}\n\n/** Recompute the derived `timeline` summary block. Mirror of cli helper. */\nexport function recomputeTimeline(doc: AtelierDocument): AtelierDocument {\n const fps = doc.canvas.fps;\n const trackGroups = doc.layers.filter(\n (l) => l.visual.type === \"group\" && (l.tags ?? []).includes(\"track\"),\n );\n\n if (trackGroups.length === 0) {\n if (doc.timeline === undefined) return doc;\n const { timeline: _omit, ...rest } = doc;\n void _omit;\n return rest as AtelierDocument;\n }\n\n const tracks: TimelineTrack[] = [];\n let totalFrames = 0;\n\n for (const track of trackGroups) {\n const tags = track.tags ?? [];\n const kind: \"video\" | \"audio\" = tags.includes(\"audio\") ? \"audio\" : \"video\";\n\n const children = doc.layers.filter(\n (l) => l.parentId === track.id && l.visual.type === kind,\n );\n\n const clips: TimelineClip[] = children\n .map((layer) => {\n const v = layer.visual as VideoVisual | AudioVisual;\n const start = v.startFrame ?? 0;\n const offset = v.sourceOffset ?? 0;\n const end = v.sourceEnd ?? offset;\n const durFrames = Math.max(0, Math.round((end - offset) * fps));\n return {\n layerId: layer.id,\n startFrame: start,\n endFrame: start + durFrames,\n source: v.src ?? \"\",\n } satisfies TimelineClip;\n })\n .sort((a, b) => a.startFrame - b.startFrame);\n\n const trackEnd = clips.reduce((m, c) => Math.max(m, c.endFrame), 0);\n if (trackEnd > totalFrames) totalFrames = trackEnd;\n\n tracks.push({ id: track.id, kind, clips });\n }\n\n const timeline: Timeline = { fps, totalFrames, tracks };\n return { ...doc, timeline };\n}\n\n/** Drop caption artifacts that conflict with a fresh rebuild of `clipLayerId`. */\nexport function stripStaleCaptionArtifacts(\n doc: AtelierDocument,\n clipLayerId: string,\n): AtelierDocument {\n const droppedIds = new Set<string>();\n const keptLayers = doc.layers.filter((layer) => {\n if (!(layer.tags ?? []).includes(\"caption\")) return true;\n if (!layer.parentId) {\n droppedIds.add(layer.id);\n return false;\n }\n if (layer.parentId === clipLayerId) {\n droppedIds.add(layer.id);\n return false;\n }\n return true;\n });\n if (droppedIds.size === 0) return doc;\n\n const states: Record<string, State> = {};\n for (const [name, st] of Object.entries(doc.states)) {\n states[name] = {\n ...st,\n deltas: st.deltas.filter((d) => !droppedIds.has(d.layer)),\n };\n }\n return { ...doc, layers: keptLayers, states };\n}\n\n// ─── Caption builder (duplicated from cli/caption-builder.ts) ────\n\nexport interface CaptionStyle {\n fontFamily?: string;\n fontSize?: number;\n fontWeight?: number | \"normal\" | \"bold\";\n textAlign?: \"left\" | \"center\" | \"right\";\n color?: string;\n yRatio?: number;\n widthRatio?: number;\n fadeSeconds?: number;\n}\n\nexport interface BuildCaptionsOptions {\n style?: CaptionStyle;\n maxWords?: number;\n pauseGap?: number;\n}\n\nconst DEFAULT_STYLE: Required<CaptionStyle> = {\n fontFamily: \"Inter\",\n fontSize: 84,\n fontWeight: \"bold\" as const,\n textAlign: \"center\" as const,\n color: \"#FFFFFF\",\n yRatio: 0.85,\n widthRatio: 0.9,\n fadeSeconds: 0.05,\n};\n\nconst DEFAULT_PHRASE_MAX_WORDS = 5;\nconst DEFAULT_PHRASE_PAUSE_GAP_SECONDS = 0.4;\nconst END_PUNCT = /[.!?,;:]\\s*$/;\n\ninterface CaptionPhrase {\n start: number;\n end: number;\n text: string;\n words: TranscriptWord[];\n}\n\nfunction flattenWords(transcript: VideoTranscript): TranscriptWord[] {\n return transcript.segments.flatMap((s) => s.words);\n}\n\nfunction groupIntoPhrases(\n transcript: VideoTranscript,\n options: { maxWords?: number; pauseGap?: number } = {},\n): CaptionPhrase[] {\n const maxWords = options.maxWords ?? DEFAULT_PHRASE_MAX_WORDS;\n const pauseGap = options.pauseGap ?? DEFAULT_PHRASE_PAUSE_GAP_SECONDS;\n\n const phrases: CaptionPhrase[] = [];\n const visibleWords = flattenWords(transcript).filter((w) => !w.hidden);\n\n let current: TranscriptWord[] = [];\n for (let i = 0; i < visibleWords.length; i++) {\n const w = visibleWords[i];\n current.push(w);\n\n const next = visibleWords[i + 1];\n const gap = next ? next.start - w.end : 0;\n const endsOnPunct = END_PUNCT.test(w.text);\n const atMax = current.length >= maxWords;\n\n if (!next || atMax || endsOnPunct || gap > pauseGap) {\n phrases.push({\n start: current[0].start,\n end: current[current.length - 1].end,\n text: current.map((c) => c.text).join(\" \"),\n words: current,\n });\n current = [];\n }\n }\n\n return phrases;\n}\n\nfunction buildCaptionLayers(\n transcript: VideoTranscript,\n canvas: AtelierDocument[\"canvas\"],\n options: BuildCaptionsOptions = {},\n): { layers: Layer[]; deltas: Delta[] } {\n const style = { ...DEFAULT_STYLE, ...options.style };\n const phrases = groupIntoPhrases(transcript, {\n maxWords: options.maxWords,\n pauseGap: options.pauseGap,\n });\n\n const layers: Layer[] = [];\n const deltas: Delta[] = [];\n const fps = canvas.fps;\n\n phrases.forEach((phrase, idx) => {\n const layerId = `caption-${idx}`;\n layers.push(buildPhraseLayer(layerId, phrase, canvas, style));\n deltas.push(...buildPhraseDeltas(layerId, phrase, style.fadeSeconds, fps));\n });\n\n return { layers, deltas };\n}\n\nfunction buildPhraseLayer(\n id: string,\n phrase: CaptionPhrase,\n canvas: AtelierDocument[\"canvas\"],\n style: Required<CaptionStyle>,\n): Layer {\n return {\n id,\n tags: [\"caption\"],\n visual: {\n type: \"text\",\n content: phrase.text,\n style: {\n fontFamily: style.fontFamily,\n fontSize: style.fontSize,\n fontWeight: style.fontWeight,\n textAlign: style.textAlign,\n color: style.color,\n },\n },\n frame: {\n x: canvas.width / 2,\n y: canvas.height * style.yRatio,\n },\n bounds: {\n width: canvas.width * style.widthRatio,\n height: Math.max(120, style.fontSize * 1.6),\n },\n anchorPoint: { x: 0.5, y: 0.5 },\n opacity: 0,\n };\n}\n\nfunction buildPhraseDeltas(\n layerId: string,\n phrase: CaptionPhrase,\n fadeSeconds: number,\n fps: number,\n): Delta[] {\n const fadeFrames = Math.max(1, Math.round(fadeSeconds * fps));\n const startFrame = Math.floor(phrase.start * fps);\n const endFrame = Math.ceil(phrase.end * fps);\n const fadeOutStart = Math.max(startFrame + 1, endFrame - fadeFrames);\n\n return [\n {\n layer: layerId,\n property: \"opacity\",\n range: [Math.max(0, startFrame - fadeFrames), startFrame],\n from: 0,\n to: 1,\n easing: \"ease-out\",\n },\n {\n layer: layerId,\n property: \"opacity\",\n range: [fadeOutStart, endFrame],\n from: 1,\n to: 0,\n easing: \"ease-in\",\n },\n ];\n}\n\n/**\n * Drop caption layers + deltas tied SOLELY to `clipLayerId`. Other clips' captions\n * pass through untouched.\n */\nfunction stripCaptionsForClip(\n doc: AtelierDocument,\n clipLayerId: string,\n): AtelierDocument {\n const droppedIds = new Set<string>();\n const keptLayers = doc.layers.filter((layer) => {\n if (!(layer.tags ?? []).includes(\"caption\")) return true;\n if (layer.parentId === clipLayerId) {\n droppedIds.add(layer.id);\n return false;\n }\n return true;\n });\n if (droppedIds.size === 0) return doc;\n\n const states: Record<string, State> = {};\n for (const [name, st] of Object.entries(doc.states)) {\n states[name] = {\n ...st,\n deltas: st.deltas.filter((d) => !droppedIds.has(d.layer)),\n };\n }\n return { ...doc, layers: keptLayers, states };\n}\n\n/**\n * Build + attach captions to a clip, parented and clip-local.\n * Mirror of cli/timeline-ops.ts:rebuildClipCaptions.\n */\nexport function rebuildClipCaptions(\n doc: AtelierDocument,\n clipLayerId: string,\n transcript: VideoTranscript,\n canvas: AtelierDocument[\"canvas\"],\n captionOptions?: BuildCaptionsOptions,\n): AtelierDocument {\n const clipSlug = clipLayerId.startsWith(\"clip-\")\n ? clipLayerId.slice(\"clip-\".length)\n : clipLayerId;\n\n let working = stripCaptionsForClip(doc, clipLayerId);\n\n const built = buildCaptionLayers(transcript, canvas, captionOptions ?? {});\n\n const idMap = new Map<string, string>();\n const renamedLayers: Layer[] = built.layers.map((layer, idx) => {\n const newId = `cap-${clipSlug}-${idx}`;\n idMap.set(layer.id, newId);\n return { ...layer, id: newId, parentId: clipLayerId };\n });\n const renamedDeltas: Delta[] = built.deltas.map((d) => ({\n ...d,\n layer: idMap.get(d.layer) ?? d.layer,\n }));\n\n working = { ...working, layers: [...working.layers, ...renamedLayers] };\n\n const stateNames = Object.keys(working.states);\n const targetStateName = stateNames.includes(\"default\")\n ? \"default\"\n : (stateNames[0] ?? \"default\");\n const states = { ...working.states };\n const existing = states[targetStateName];\n if (existing) {\n states[targetStateName] = {\n ...existing,\n deltas: [...existing.deltas, ...renamedDeltas],\n };\n } else {\n states[targetStateName] = { duration: 0, deltas: renamedDeltas };\n }\n\n return { ...working, states };\n}\n\n// ─── ffprobe (duplicated from cli/silence-detect.ts) ──────────────\n\n/**\n * Probe source media duration via ffprobe, in seconds. Duplicated from\n * cli/silence-detect.ts so the MCP package doesn't need to depend on cli.\n */\nexport async function probeDuration(sourcePath: string): Promise<number> {\n const stdout = await runCapture(\"ffprobe\", [\n \"-v\", \"error\",\n \"-show_entries\", \"format=duration\",\n \"-of\", \"csv=p=0\",\n sourcePath,\n ]);\n const n = parseFloat(stdout.trim());\n if (!Number.isFinite(n) || n <= 0) {\n throw new Error(`ffprobe returned invalid duration for ${sourcePath}: \"${stdout}\"`);\n }\n return n;\n}\n\nfunction runCapture(cmd: string, args: string[]): Promise<string> {\n return new Promise((resolvePromise, reject) => {\n const child = spawn(cmd, args);\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (d) => { stdout += d.toString(); });\n child.stderr.on(\"data\", (d) => { stderr += d.toString(); });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (code === 0) resolvePromise(stdout);\n else reject(new Error(`${cmd} exited ${code}: ${stderr}`));\n });\n });\n}\n","// #mcp-rename-media-tool — MCP wrapper around `renameMedia` for the atomic\n// media-file rename cascade. Slice C of the v1.0 creator-flow batch.\n//\n// The wrapper:\n// 1. Validates the old/new basenames defensively before the core call\n// (path traversal, leading-dot, control chars). The underlying\n// `renameMedia` does NOT validate — it joins straight into media/ —\n// so this is the single line of defense for MCP callers.\n// 2. Invokes the cascade. On success (and !dryRun) reloads the project\n// document into the supplied DocumentStore so subsequent tool calls\n// see the post-rename doc state.\n// 3. Wraps any thrown error into the standard MCP `{ error }` envelope.\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type { DocumentStore } from \"../store.js\";\nimport {\n renameMedia,\n isValidMediaBasenameForRename,\n} from \"../lib/rename-media.js\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve, sep } from \"node:path\";\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── v1.0 rename-media tool ──────\n server.tool(\n \"atelier_rename_media\",\n \"Rename a media file in a project, cascading the rename through transcripts and the project document. Atomic with rollback on partial failure.\",\n {\n documentId: z.string().describe(\"Document ID\"),\n projectDir: z.string().describe(\"Absolute project directory path\"),\n oldBasename: z.string().describe(\"Current basename inside media/, e.g. 'IMG_7346.MOV'\"),\n newBasename: z.string().describe(\"New basename inside media/\"),\n dryRun: z.boolean().optional().describe(\"If true, compute the result without writing\"),\n workspaceDir: z.string().optional().describe(\"Workspace root for security scoping (defaults to process.cwd())\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ documentId, projectDir, oldBasename, newBasename, dryRun, workspaceDir }) => {\n try {\n // ── path-traversal defense ──────\n // `renameMedia` joins straight into <projectDir>/media/<basename>,\n // so a crafted `../../etc/passwd` would otherwise escape the media\n // dir. Reject any separator / leading-dot / control char up front.\n if (!isValidMediaBasenameForRename(oldBasename)) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: \"invalid oldBasename\" }) }],\n isError: true as const,\n };\n }\n if (!isValidMediaBasenameForRename(newBasename)) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: \"invalid newBasename\" }) }],\n isError: true as const,\n };\n }\n\n // ── workspace scoping (Aegis Finding 1, TD-2026-05-27) ──────\n // The MCP tool previously accepted an unconstrained `projectDir`.\n // Bound the rename to the workspace root: by default `process.cwd()`\n // (the MCP server is launched from the workspace), or an explicit\n // `workspaceDir` argument. Reject any projectDir that resolves\n // outside that root.\n const workspaceRoot = resolve(workspaceDir ?? process.cwd());\n const resolvedProject = resolve(projectDir);\n if (\n resolvedProject !== workspaceRoot &&\n !resolvedProject.startsWith(workspaceRoot + sep)\n ) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: `projectDir must be inside workspace ${workspaceRoot}` }) }],\n isError: true as const,\n };\n }\n if (!existsSync(join(resolvedProject, \"project.atelier\"))) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: \"projectDir does not contain project.atelier\" }) }],\n isError: true as const,\n };\n }\n\n const result = await renameMedia({\n projectDir: resolvedProject,\n oldBasename,\n newBasename,\n ...(dryRun !== undefined ? { dryRun } : {}),\n });\n\n // Reload the doc into the store unless this was a dryRun.\n if (!dryRun) {\n const docPath = join(resolvedProject, \"project.atelier\");\n const raw = readFileSync(docPath, \"utf-8\");\n const parsed = parseAtelier(raw);\n if (parsed.success) {\n store.set(documentId, parsed.data, \"system\");\n }\n }\n\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, result }) }],\n };\n } catch (e) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: (e as Error).message }) }],\n isError: true as const,\n };\n }\n },\n );\n}\n","// #mcp-rename-media — atomic media-file rename cascade for the MCP rename tool.\n//\n// **Intentional duplication** of `packages/cli/src/lib/rename-media.ts`.\n// MCP cannot import from `@a-company/atelier` (the CLI package) because\n// `cli → mcp` already runs in the dep graph — re-importing back would close\n// the cycle. The same duplication convention is used by `./timeline-ops.ts`\n// and by recipes.ts / overlays.ts / effective-transcript.ts / media-notes.ts\n// in the tools/ directory.\n//\n// If the canonical implementation in cli/lib/rename-media.ts changes semantics,\n// this file MUST be kept in sync — there is no shared package between mcp and\n// cli for these primitives in v1.0. Lifting media-cascade ops into a shared\n// package is tracked alongside the timeline-ops follow-up.\n//\n// Behavior mirror (see cli/lib/rename-media.ts for the long-form spec):\n// 1. media/<old> → media/<new>\n// 2. transcripts/<old-stem>.json → transcripts/<new-stem>.json (when present)\n// 3. project.atelier: rewrite assets[*].src, layers[*].visual.src,\n// timeline.tracks[*].clips[*].source via `recomputeTimeline`\n// 4. Warnings for DESIGN/SCRIPT/STORYBOARD.md references (no rewrite)\n// Two-phase with rollback so a mid-op failure never leaves a half-renamed state.\n\nimport {\n existsSync,\n readFileSync,\n renameSync,\n writeFileSync,\n} from \"node:fs\";\nimport { extname, join, resolve } from \"node:path\";\nimport type { AtelierDocument, Asset, Layer } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\nimport { recomputeTimeline } from \"./timeline-ops.js\";\n\n// ── Per-project mutex (Aegis Finding 3, TD-2026-05-27) ───────────────\n// In-process serialization keyed by resolved projectDir. Prevents two\n// concurrent `renameMedia` calls on the SAME project from racing through\n// the two-phase fs ops and corrupting the doc / leaving orphaned files.\n// Different projects do NOT block each other (each gets its own queue).\n// MUST mirror the cli/lib/rename-media.ts implementation per the duplication\n// convention — see header comment.\nconst renameLocks = new Map<string, Promise<unknown>>();\n\n/** Options for `renameMedia`. */\nexport interface RenameMediaOptions {\n /** Absolute path to the project root (contains project.atelier + media/). */\n projectDir: string;\n /** Basename inside `media/`, e.g. `IMG_7346.MOV`. */\n oldBasename: string;\n /** New basename inside `media/`. */\n newBasename: string;\n /** When true, computes the result but skips every disk write. */\n dryRun?: boolean;\n}\n\n/** Result of `renameMedia`. */\nexport interface RenameMediaResult {\n docUpdated: boolean;\n transcriptRenamed: boolean;\n assetKeysUpdated: string[];\n layersUpdated: string[];\n timelineRegenerated: boolean;\n warnings: string[];\n}\n\nfunction readAtelierDoc(absPath: string): AtelierDocument {\n const raw = readFileSync(absPath, \"utf-8\");\n const parsed = parseAtelier(raw);\n if (parsed.success) return parsed.data as AtelierDocument;\n return JSON.parse(raw) as AtelierDocument;\n}\n\nfunction stripExt(name: string): string {\n const ext = extname(name);\n return ext ? name.slice(0, -ext.length) : name;\n}\n\nfunction srcReferencesBasename(src: string | undefined, oldBasename: string): boolean {\n if (typeof src !== \"string\" || src.length === 0) return false;\n if (src === oldBasename) return true;\n if (src === `media/${oldBasename}`) return true;\n if (src.endsWith(`/${oldBasename}`)) return true;\n return false;\n}\n\nfunction rewriteSrc(src: string, oldBasename: string, newBasename: string): string {\n if (src === oldBasename) return newBasename;\n if (src === `media/${oldBasename}`) return `media/${newBasename}`;\n if (src.endsWith(`/${oldBasename}`)) {\n return src.slice(0, -oldBasename.length) + newBasename;\n }\n return src;\n}\n\nexport function applyMediaRenameToDoc(\n doc: AtelierDocument,\n oldBasename: string,\n newBasename: string,\n): { doc: AtelierDocument; assetKeysUpdated: string[]; layersUpdated: string[] } {\n const assetKeysUpdated: string[] = [];\n const layersUpdated: string[] = [];\n\n let newAssets: Record<string, Asset> | undefined = undefined;\n if (doc.assets && typeof doc.assets === \"object\") {\n const out: Record<string, Asset> = {};\n for (const [key, asset] of Object.entries(doc.assets)) {\n if (asset && typeof asset === \"object\" && srcReferencesBasename(asset.src, oldBasename)) {\n out[key] = { ...asset, src: rewriteSrc(asset.src, oldBasename, newBasename) };\n assetKeysUpdated.push(key);\n } else {\n out[key] = asset;\n }\n }\n newAssets = out;\n }\n\n const newLayers: Layer[] = doc.layers.map((layer) => {\n const v = layer.visual;\n if (!v || (v.type !== \"video\" && v.type !== \"audio\" && v.type !== \"image\")) {\n return layer;\n }\n const visualWithSrc = v as { type: string; src?: string };\n if (!srcReferencesBasename(visualWithSrc.src, oldBasename)) return layer;\n layersUpdated.push(layer.id);\n return {\n ...layer,\n visual: {\n ...v,\n src: rewriteSrc(visualWithSrc.src as string, oldBasename, newBasename),\n },\n } as Layer;\n });\n\n const out: AtelierDocument = { ...doc, layers: newLayers };\n if (newAssets !== undefined) out.assets = newAssets;\n return { doc: out, assetKeysUpdated, layersUpdated };\n}\n\nexport function scanArtifactsForOldBasename(\n projectDir: string,\n oldBasename: string,\n): string[] {\n const warnings: string[] = [];\n const artifactFiles = [\"DESIGN.md\", \"SCRIPT.md\", \"STORYBOARD.md\"];\n for (const name of artifactFiles) {\n const absPath = join(projectDir, name);\n if (!existsSync(absPath)) continue;\n try {\n const raw = readFileSync(absPath, \"utf-8\");\n if (raw.includes(oldBasename)) {\n warnings.push(`${name} references old path '${oldBasename}'`);\n }\n } catch {\n // Non-fatal.\n }\n }\n return warnings;\n}\n\n/**\n * Atomic media-rename cascade with two-phase rollback. See header comment +\n * cli/lib/rename-media.ts for the long-form spec.\n */\nexport async function renameMedia(opts: RenameMediaOptions): Promise<RenameMediaResult> {\n const projectDir = resolve(opts.projectDir);\n const oldBasename = opts.oldBasename;\n const newBasename = opts.newBasename;\n\n if (oldBasename === newBasename) {\n return {\n docUpdated: false,\n transcriptRenamed: false,\n assetKeysUpdated: [],\n layersUpdated: [],\n timelineRegenerated: false,\n warnings: [],\n };\n }\n\n // ── per-project critical section ────────────────────────────\n // See cli/lib/rename-media.ts for the long-form rationale (Aegis Finding 3).\n const lockKey = projectDir;\n const prev = renameLocks.get(lockKey) ?? Promise.resolve();\n const run = prev.catch(() => {}).then(() => renameMediaImpl(projectDir, oldBasename, newBasename, opts.dryRun));\n renameLocks.set(lockKey, run);\n try {\n return await run;\n } finally {\n if (renameLocks.get(lockKey) === run) renameLocks.delete(lockKey);\n }\n}\n\nasync function renameMediaImpl(\n projectDir: string,\n oldBasename: string,\n newBasename: string,\n dryRun: boolean | undefined,\n): Promise<RenameMediaResult> {\n const mediaDir = join(projectDir, \"media\");\n if (!existsSync(mediaDir)) {\n throw new Error(`renameMedia: project has no media/ dir at ${mediaDir}`);\n }\n const mediaOldAbs = join(mediaDir, oldBasename);\n const mediaNewAbs = join(mediaDir, newBasename);\n if (!existsSync(mediaOldAbs)) {\n throw new Error(`renameMedia: media file not found: ${mediaOldAbs}`);\n }\n if (existsSync(mediaNewAbs)) {\n throw new Error(`renameMedia: destination file already exists: ${mediaNewAbs}`);\n }\n\n const transcriptsDir = join(projectDir, \"transcripts\");\n const transcriptOldAbs = join(transcriptsDir, `${stripExt(oldBasename)}.json`);\n const transcriptNewAbs = join(transcriptsDir, `${stripExt(newBasename)}.json`);\n const transcriptExists = existsSync(transcriptOldAbs);\n\n const docPath = join(projectDir, \"project.atelier\");\n if (!existsSync(docPath)) {\n throw new Error(`renameMedia: missing project.atelier at ${docPath}`);\n }\n const originalDoc = readAtelierDoc(docPath);\n const walked = applyMediaRenameToDoc(originalDoc, oldBasename, newBasename);\n\n const hadTimeline = originalDoc.timeline !== undefined;\n const newDoc = recomputeTimeline(walked.doc);\n const hasTimelineAfter = newDoc.timeline !== undefined;\n const timelineRegenerated = hadTimeline || hasTimelineAfter;\n\n const warnings = scanArtifactsForOldBasename(projectDir, oldBasename);\n\n if (dryRun === true) {\n return {\n docUpdated: false,\n transcriptRenamed: false,\n assetKeysUpdated: walked.assetKeysUpdated,\n layersUpdated: walked.layersUpdated,\n timelineRegenerated: false,\n warnings,\n };\n }\n\n // Phase 2 — disk writes with rollback.\n // NOTE: Per Aegis security audit (TD-2026-05-27, Finding 2),\n // `renameSync` does NOT follow symlinks — it renames the link itself.\n // This is the desired behavior: a symlink in media/ stays a symlink\n // after rename. Dangling symlinks at the destination are extremely\n // rare in the local-only threat model; tracked as an aspect\n // (~rename-symlink-passthrough). If symlink handling becomes\n // load-bearing, switch to `lstatSync` for destination checks.\n let mediaRenamed = false;\n try {\n renameSync(mediaOldAbs, mediaNewAbs);\n mediaRenamed = true;\n } catch (err) {\n throw new Error(\n `renameMedia: failed to rename media file: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n let transcriptRenamed = false;\n if (transcriptExists) {\n try {\n renameSync(transcriptOldAbs, transcriptNewAbs);\n transcriptRenamed = true;\n } catch (err) {\n try {\n renameSync(mediaNewAbs, mediaOldAbs);\n } catch (rbErr) {\n console.error(\n `renameMedia: CRITICAL — rollback of media rename failed: ${rbErr instanceof Error ? rbErr.message : String(rbErr)}`,\n );\n }\n throw new Error(\n `renameMedia: failed to rename transcript: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n try {\n writeFileSync(docPath, JSON.stringify(newDoc, null, 2), \"utf-8\");\n } catch (err) {\n if (transcriptRenamed) {\n try {\n renameSync(transcriptNewAbs, transcriptOldAbs);\n } catch (rbErr) {\n console.error(\n `renameMedia: CRITICAL — rollback of transcript rename failed: ${rbErr instanceof Error ? rbErr.message : String(rbErr)}`,\n );\n }\n }\n if (mediaRenamed) {\n try {\n renameSync(mediaNewAbs, mediaOldAbs);\n } catch (rbErr) {\n console.error(\n `renameMedia: CRITICAL — rollback of media rename failed: ${rbErr instanceof Error ? rbErr.message : String(rbErr)}`,\n );\n }\n }\n throw new Error(\n `renameMedia: failed to write project.atelier: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n return {\n docUpdated: true,\n transcriptRenamed,\n assetKeysUpdated: walked.assetKeysUpdated,\n layersUpdated: walked.layersUpdated,\n timelineRegenerated,\n warnings,\n };\n}\n\n/**\n * Path-traversal defense for media basenames. Rejects any value containing\n * a directory separator, `..`, leading `.`, or NUL / control bytes. Used by\n * the MCP tool wrapper and re-implementable by the studio HTTP layer.\n */\nexport function isValidMediaBasenameForRename(name: unknown): name is string {\n if (typeof name !== \"string\") return false;\n if (name.length === 0) return false;\n if (name !== name.trim()) return false;\n if (name.includes(\"/\") || name.includes(\"\\\\\")) return false;\n if (name === \".\" || name === \"..\") return false;\n if (name.startsWith(\".\")) return false;\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f]/.test(name)) return false;\n return true;\n}\n","// #mcp-docs-tools — MCP tools for the v1.0 doc-management surface: create,\n// duplicate, delete, and list .atelier docs inside a workspace project.\n//\n// Defense-in-depth posture (mirrors `./rename-media.ts`):\n// 1. Workspace scoping: `projectDir` (or `workspaceDir + projectName`) MUST\n// resolve inside `workspaceDir` (defaulting to `process.cwd()`). Reject\n// out-of-workspace requests up front.\n// 2. For mutate-style tools (create, duplicate), `projectDir` MUST contain a\n// `project.atelier`. Reject ghost-directory targets.\n// 3. After mutation, reload the affected doc into the supplied DocumentStore\n// under `documentId` with source `\"llm\"` so the live bridge sees the\n// post-mutation state. For delete, only reload if the user's `documentId`\n// was the deleted doc — multi-carousel manifest reload is handled by the\n// studio's WS filesystem watcher, not this layer.\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve, sep } from \"node:path\";\n\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\n\nimport type { DocumentStore } from \"../store.js\";\nimport {\n createDoc,\n deleteDoc,\n duplicateDoc,\n listDocs,\n} from \"../lib/doc-management.js\";\nimport { isValidDocName } from \"../lib/doc-management-types.js\";\n\n// ── Helpers ──────────────────────────────────────────────────────\n\nfunction errorEnvelope(message: string) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }],\n isError: true as const,\n };\n}\n\nfunction successEnvelope(payload: Record<string, unknown>) {\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ success: true, ...payload }) }],\n };\n}\n\n/**\n * Resolve a `projectDir` under a workspace root, with the same posture as\n * rename-media.ts: workspaceDir defaults to process.cwd(); projectDir must\n * be equal to or a descendant of workspaceDir.\n */\nfunction resolveProjectInWorkspace(\n projectDir: string,\n workspaceDir: string | undefined,\n): { ok: true; workspaceAbs: string; projectAbs: string } | { ok: false; error: string } {\n const workspaceAbs = resolve(workspaceDir ?? process.cwd());\n const projectAbs = resolve(projectDir);\n if (projectAbs !== workspaceAbs && !projectAbs.startsWith(workspaceAbs + sep)) {\n return { ok: false, error: `projectDir must be inside workspace ${workspaceAbs}` };\n }\n return { ok: true, workspaceAbs, projectAbs };\n}\n\nfunction readDocFromDisk(absPath: string): AtelierDocument | undefined {\n try {\n const raw = readFileSync(absPath, \"utf-8\");\n const parsed = parseAtelier(raw);\n if (parsed.success) return parsed.data as AtelierDocument;\n return JSON.parse(raw) as AtelierDocument;\n } catch {\n return undefined;\n }\n}\n\nexport function register(server: McpServer, store: DocumentStore): void {\n // ── v1.0.x doc tools ──────\n\n // ── 1. atelier_create_doc ────────────────────────────────────\n server.tool(\n \"atelier_create_doc\",\n \"Create a new .atelier doc inside a workspace project. Optionally append it to a carousel's slides[].\",\n {\n documentId: z.string().describe(\"Document ID under which to reload the affected doc\"),\n projectDir: z.string().describe(\"Absolute project directory (must contain project.atelier)\"),\n workspaceDir: z.string().optional().describe(\"Workspace root for security scoping (defaults to process.cwd())\"),\n name: z.string().describe(\"Human-typed doc name; slugged internally to a filesystem-safe stem\"),\n kind: z.enum([\"video\", \"image\", \"carousel\"]).describe(\"Doc kind\"),\n asCarouselSlide: z.boolean().optional().describe(\"If true, write under slides/ and append a SlideRef to carouselDocPath\"),\n carouselDocPath: z.string().optional().describe(\"Absolute path to the carousel doc whose slides[] to mutate (required when asCarouselSlide:true)\"),\n insertAt: z.number().int().optional().describe(\"Index in carousel slides[] (default = append)\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, projectDir, workspaceDir, name, kind, asCarouselSlide, carouselDocPath, insertAt }) => {\n try {\n if (!isValidDocName(name)) return errorEnvelope(\"invalid doc name\");\n\n const scope = resolveProjectInWorkspace(projectDir, workspaceDir);\n if (!scope.ok) return errorEnvelope(scope.error);\n if (!existsSync(join(scope.projectAbs, \"project.atelier\"))) {\n return errorEnvelope(\"projectDir does not contain project.atelier\");\n }\n\n // If asCarouselSlide is requested, ensure the carousel path is also\n // inside the workspace (defense in depth).\n if (asCarouselSlide && carouselDocPath) {\n const carouselAbs = resolve(carouselDocPath);\n if (carouselAbs !== scope.workspaceAbs && !carouselAbs.startsWith(scope.workspaceAbs + sep)) {\n return errorEnvelope(`carouselDocPath must be inside workspace ${scope.workspaceAbs}`);\n }\n }\n\n const result = createDoc({\n projectDir: scope.projectAbs,\n name,\n kind,\n ...(asCarouselSlide !== undefined ? { asCarouselSlide } : {}),\n ...(carouselDocPath !== undefined ? { carouselDocPath } : {}),\n ...(insertAt !== undefined ? { insertAt } : {}),\n });\n\n // Reload: if we appended a SlideRef, reload the carousel manifest; else\n // reload the newly-created doc itself.\n const reloadTarget = asCarouselSlide && carouselDocPath\n ? resolve(carouselDocPath)\n : result.newDocAbsPath;\n const doc = readDocFromDisk(reloadTarget);\n if (doc) store.set(documentId, doc, \"llm\");\n\n const payload: Record<string, unknown> = { docPath: result.newDocPath };\n if (result.appendedSlideIndex !== undefined) {\n payload.appendedSlideIndex = result.appendedSlideIndex;\n }\n return successEnvelope(payload);\n } catch (e) {\n return errorEnvelope((e as Error).message);\n }\n },\n );\n\n // ── 2. atelier_duplicate_doc ─────────────────────────────────\n server.tool(\n \"atelier_duplicate_doc\",\n \"Duplicate an existing .atelier doc inside a project. Optionally appends a SlideRef to the project's carousel manifest (requires the source to live directly under slides/).\",\n {\n documentId: z.string().describe(\"Document ID under which to reload the affected doc\"),\n projectDir: z.string().describe(\"Absolute project directory (must contain project.atelier)\"),\n workspaceDir: z.string().optional().describe(\"Workspace root for security scoping (defaults to process.cwd())\"),\n sourceDocPath: z.string().describe(\"Project-relative path of the doc to duplicate (e.g. 'slides/slide-1.atelier')\"),\n appendSlideRef: z.boolean().optional().describe(\"If true, append a SlideRef pointing at the duplicate to the project manifest\"),\n },\n { readOnlyHint: false, destructiveHint: false },\n async ({ documentId, projectDir, workspaceDir, sourceDocPath, appendSlideRef }) => {\n try {\n const scope = resolveProjectInWorkspace(projectDir, workspaceDir);\n if (!scope.ok) return errorEnvelope(scope.error);\n if (!existsSync(join(scope.projectAbs, \"project.atelier\"))) {\n return errorEnvelope(\"projectDir does not contain project.atelier\");\n }\n\n const report = duplicateDoc({\n projectDir: scope.projectAbs,\n sourceDocPath,\n ...(appendSlideRef !== undefined ? { appendSlideRef } : {}),\n });\n\n // Reload: if a SlideRef was appended, reload the manifest; else reload\n // the duplicate itself.\n const reloadTarget = appendSlideRef\n ? join(scope.projectAbs, \"project.atelier\")\n : join(scope.projectAbs, report.newDocPath);\n const doc = readDocFromDisk(reloadTarget);\n if (doc) store.set(documentId, doc, \"llm\");\n\n return successEnvelope(report as unknown as Record<string, unknown>);\n } catch (e) {\n return errorEnvelope((e as Error).message);\n }\n },\n );\n\n // ── 3. atelier_delete_doc ────────────────────────────────────\n server.tool(\n \"atelier_delete_doc\",\n \"Delete any .atelier doc (including project.atelier), scrubbing matching SlideRefs across the workspace and reporting dangling RefVisual layers.\",\n {\n documentId: z.string().describe(\"Document ID — if equal to the deleted doc's path, the studio handles fallback\"),\n workspaceDir: z.string().optional().describe(\"Workspace root for security scoping (defaults to process.cwd())\"),\n projectName: z.string().describe(\"Project subdir name inside workspaceDir\"),\n docPath: z.string().describe(\"Project-relative path of the doc to delete (e.g. 'slides/slide-2.atelier')\"),\n },\n { readOnlyHint: false, destructiveHint: true },\n async ({ documentId: _documentId, workspaceDir, projectName, docPath }) => {\n try {\n const workspaceAbs = resolve(workspaceDir ?? process.cwd());\n const projectAbs = resolve(join(workspaceAbs, projectName));\n // projectName must resolve inside workspaceAbs (e.g. reject \"../escape\").\n if (projectAbs !== workspaceAbs && !projectAbs.startsWith(workspaceAbs + sep)) {\n return errorEnvelope(`projectName must resolve inside workspace ${workspaceAbs}`);\n }\n if (!existsSync(join(projectAbs, \"project.atelier\"))) {\n return errorEnvelope(\"project does not contain project.atelier\");\n }\n\n const report = deleteDoc({\n workspaceDir: workspaceAbs,\n projectName,\n docPath,\n });\n\n // The studio's WS layer handles fallback when the active documentId\n // was the deleted doc — that is intentionally NOT this layer's\n // concern. We do nothing on the store here (no reload target exists\n // for the deleted doc).\n void _documentId;\n\n return successEnvelope(report as unknown as Record<string, unknown>);\n } catch (e) {\n return errorEnvelope((e as Error).message);\n }\n },\n );\n\n // ── 4. atelier_list_docs ─────────────────────────────────────\n server.tool(\n \"atelier_list_docs\",\n \"Enumerate every .atelier doc inside a project (flat alphabetical by project-relative path). Returns each as { path, kind? }.\",\n {\n projectDir: z.string().describe(\"Absolute project directory\"),\n workspaceDir: z.string().optional().describe(\"Workspace root for security scoping (defaults to process.cwd())\"),\n },\n { readOnlyHint: true, destructiveHint: false },\n async ({ projectDir, workspaceDir }) => {\n try {\n const scope = resolveProjectInWorkspace(projectDir, workspaceDir);\n if (!scope.ok) return errorEnvelope(scope.error);\n\n const docs = listDocs(scope.projectAbs);\n return successEnvelope({ docs });\n } catch (e) {\n return errorEnvelope((e as Error).message);\n }\n },\n );\n}\n","// #mcp-lib-doc-management — doc-management helpers for the MCP doc tools.\n//\n// **Intentional duplication** of `packages/cli/src/lib/doc-management.ts`.\n// MCP cannot import from `@a-company/atelier` (the CLI package) because\n// `cli → mcp` already runs in the dep graph — re-importing back would close\n// the cycle. The same duplication convention is used by clips.ts,\n// rename-media.ts, and timeline-ops.ts (all carry this header).\n//\n// If the canonical helpers in cli/lib/doc-management.ts change semantics,\n// this file MUST be kept in sync — there is no shared package between mcp\n// and cli for these primitives in v1.0. Lifting to a shared package (e.g.\n// `atelier-doc-management`) is tracked as a Unit-0.5 follow-up.\n//\n// Scope (v1.0, see doc-management-types.ts for the type contracts):\n// - createDoc: scaffold a fresh .atelier; optionally append a SlideRef\n// to a target carousel's slides[].\n// - duplicateDoc: copy a doc to \"<stem>-copy.atelier\"; optionally append\n// a SlideRef.\n// - deleteDoc: unlink a doc; scrub workspace-wide SlideRefs that\n// pointed at it; report dangling RefVisual layers\n// (not auto-removed).\n// - listDocs: enumerate .atelier files in a project root + slides/.\n//\n// ~doc-cycle-v1-simple-check\n// Cycle-check simplification (v1, deliberate divergence from the CLI):\n// The canonical CLI version delegates the carousel append to\n// `composeCarouselProject`, which runs the full transitive cycle walk via\n// `ref-cycle.ts`. The MCP duplicate has no compose-* helpers (the cycle\n// between mcp and cli prevents importing them), so we use a simple direct-\n// duplicate check before appending a SlideRef: refuse if the target src is\n// already in slides[]. This covers the common case; deeper transitive\n// cycles can still pass through. Lifting to a shared package would let us\n// call the canonical cycle walker — tracked as a Unit-0.5 follow-up.\n\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { basename, dirname, extname, isAbsolute, join, relative, resolve } from \"node:path\";\n\nimport type { AtelierDocument, Layer, RefVisual, SlideRef } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\n\nimport {\n isValidDocName,\n type CreateDocOptions,\n type DeleteDocOptions,\n type DocDeleteCascadeReport,\n type DocDuplicateReport,\n type DocListEntry,\n type DuplicateDocOptions,\n} from \"./doc-management-types.js\";\n\n// ─── Slugifier (inline; do NOT import from cli/compose-video-project.ts) ───\n\n/**\n * Slug an arbitrary doc display name into a filesystem-safe stem.\n * Mirror of cli/lib/doc-management.ts:slugifyBasename.\n *\n * Algorithm:\n * 1. Strip a trailing extension (single dot, last group of non-dot bytes).\n * 2. Lowercase.\n * 3. Replace runs of non-[a-z0-9] with `-`.\n * 4. Trim leading/trailing dashes.\n *\n * e.g. `Hello World.atelier` → `hello-world`.\n */\nfunction slugifyBasename(name: string): string {\n const noExt = name.replace(/\\.[^.]+$/, \"\");\n const slugged = noExt.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n return slugged;\n}\n\n// ─── readAtelierDoc — mirror of the rename-media.ts local helper ─────\n\nfunction readAtelierDoc(absPath: string): AtelierDocument {\n const raw = readFileSync(absPath, \"utf-8\");\n const parsed = parseAtelier(raw);\n if (parsed.success) return parsed.data as AtelierDocument;\n return JSON.parse(raw) as AtelierDocument;\n}\n\n// ─── Scaffolder ─────────────────────────────────────────────────────\n\nfunction scaffoldDoc(slug: string, kind: \"video\" | \"image\" | \"carousel\"): AtelierDocument {\n const base: AtelierDocument = {\n version: \"1.0\",\n name: slug,\n kind,\n canvas: { width: 1080, height: 1920, fps: 30 },\n layers: [],\n states: { default: { duration: 1, deltas: [] } },\n };\n if (kind === \"carousel\") {\n base.slides = [];\n }\n return base;\n}\n\n// ─── createDoc ───────────────────────────────────────────────────────\n\n/**\n * Result of `createDoc` — keeps the MCP-specific shape (`newDocPath` +\n * `newDocAbsPath`) deliberately diverging from the CLI's `{ doc, docPath }`.\n * The MCP tool wrapper consumes `newDocAbsPath` to reload the right doc into\n * the per-session store after writing.\n */\nexport interface CreateDocResult {\n /** Project-relative path of the new doc. */\n newDocPath: string;\n /** Absolute path of the new doc. */\n newDocAbsPath: string;\n /** When the new doc was appended as a SlideRef: its index in slides[]. */\n appendedSlideIndex?: number;\n}\n\n/**\n * Create a new `.atelier` doc inside a project.\n *\n * - Validates name via `isValidDocName`.\n * - Slugs to a filesystem-safe stem; collision-suffixes -1, -2, ... up to 999.\n * - For `asCarouselSlide:true`, writes under `slides/<slug>.atelier` AND\n * appends a SlideRef to `opts.carouselDocPath`'s slides[]. The SlideRef src\n * is relative to `projectDir` (the dual-base resolver tries projectDir\n * first, so writing srcs project-relative makes them stable when the\n * carousel doc moves around within the project subtree).\n * - Cycle check (v1, see ~doc-cycle-v1-simple-check at top of file): refuses\n * if the new src already exists in slides[].\n */\nexport function createDoc(opts: CreateDocOptions): CreateDocResult {\n if (!isValidDocName(opts.name)) {\n throw new Error(\"invalid doc name\");\n }\n\n const projectDir = resolve(opts.projectDir);\n const slug = slugifyBasename(opts.name);\n if (slug.length === 0) {\n throw new Error(\"invalid doc name\");\n }\n\n // ── Compute target path with collision suffix ─────────────────\n const subdir = opts.asCarouselSlide ? \"slides\" : \"\";\n const baseDir = subdir ? join(projectDir, subdir) : projectDir;\n\n let finalStem = slug;\n let attempt = 0;\n while (existsSync(join(baseDir, `${finalStem}.atelier`))) {\n attempt += 1;\n if (attempt > 999) {\n throw new Error(`createDoc: could not find a non-colliding stem for \"${slug}\"`);\n }\n finalStem = `${slug}-${attempt}`;\n }\n\n const newDocAbsPath = join(baseDir, `${finalStem}.atelier`);\n const newDocPath = subdir ? `${subdir}/${finalStem}.atelier` : `${finalStem}.atelier`;\n\n // ── Scaffold + write ──────────────────────────────────────────\n const newDoc = scaffoldDoc(finalStem, opts.kind);\n mkdirSync(dirname(newDocAbsPath), { recursive: true });\n writeFileSync(newDocAbsPath, JSON.stringify(newDoc, null, 2), \"utf-8\");\n\n // ── Carousel-slide append (optional) ──────────────────────────\n if (opts.asCarouselSlide) {\n if (!opts.carouselDocPath) {\n throw new Error(\"createDoc: asCarouselSlide requires carouselDocPath\");\n }\n const carouselAbs = resolve(opts.carouselDocPath);\n if (!existsSync(carouselAbs)) {\n throw new Error(`createDoc: carouselDocPath does not exist: ${carouselAbs}`);\n }\n const carouselDoc = readAtelierDoc(carouselAbs);\n if (carouselDoc.kind !== \"carousel\") {\n throw new Error(`createDoc: carouselDocPath is not a carousel doc (kind=${carouselDoc.kind ?? \"video\"})`);\n }\n\n // SlideRef.src is computed relative to projectDir (NOT to the carousel\n // doc's directory). Matches the dual-base resolver's preferred basis and\n // stays stable when carousel docs live at non-root paths. When the\n // carousel is at the project root the two bases coincide.\n const slideSrc = relative(projectDir, newDocAbsPath).split(\"\\\\\").join(\"/\");\n\n // v1 cycle simplification (see ~doc-cycle-v1-simple-check at top of\n // file): refuse if the src is already in slides[].\n const slides = carouselDoc.slides ?? [];\n if (slides.some((s) => s.src === slideSrc)) {\n // Roll back the freshly-written file so we don't leave litter.\n try { unlinkSync(newDocAbsPath); } catch { /* best-effort */ }\n throw new Error(`createDoc: slide ${slideSrc} already exists in carousel`);\n }\n\n // Compute insertion index.\n const insertAt =\n typeof opts.insertAt === \"number\" && opts.insertAt >= 0 && opts.insertAt <= slides.length\n ? opts.insertAt\n : slides.length;\n\n // Note: SlideRef.label is NOT populated here. Matches the CLI's createDoc\n // posture — `composeCarouselProject` only sets `label` when the caller\n // passes one; createDoc does not, so the slide has no label by default.\n const newSlide: SlideRef = { src: slideSrc };\n const newSlides = [...slides.slice(0, insertAt), newSlide, ...slides.slice(insertAt)];\n const updatedCarousel: AtelierDocument = { ...carouselDoc, slides: newSlides };\n\n writeFileSync(carouselAbs, JSON.stringify(updatedCarousel, null, 2), \"utf-8\");\n\n return { newDocPath, newDocAbsPath, appendedSlideIndex: insertAt };\n }\n\n return { newDocPath, newDocAbsPath };\n}\n\n// ─── duplicateDoc ────────────────────────────────────────────────────\n\n/**\n * Duplicate an existing doc inside a project. Source is given as a project-\n * relative path; destination is `<stem>-copy.atelier` (with -copy-2, -copy-3…\n * collision suffixes — there is intentionally no `-copy-1` since `-copy` is\n * conceptually copy #1).\n *\n * - When `appendSlideRef:true`, requires the source to live directly under\n * `slides/` (matches the CLI guard exactly: `dirname === \"slides\"`, NOT\n * \"starts with slides/\"). Locates the project's carousel manifest at\n * `project.atelier`, and appends a SlideRef pointing at the duplicate.\n * Refuses (v1 simplification, see ~doc-cycle-v1-simple-check at top of\n * file) if the duplicate src already exists in slides[].\n */\nexport function duplicateDoc(opts: DuplicateDocOptions): DocDuplicateReport {\n const projectDir = resolve(opts.projectDir);\n\n const sourceAbs = join(projectDir, opts.sourceDocPath);\n if (!existsSync(sourceAbs)) {\n throw new Error(`duplicateDoc: source doc not found: ${opts.sourceDocPath}`);\n }\n\n // Parse the source so we preserve its content verbatim (including layer ids).\n const sourceDoc = readAtelierDoc(sourceAbs);\n\n // ── Compute \"<stem>-copy[-N].atelier\" with collision suffix ───\n const sourceDir = dirname(sourceAbs);\n const sourceBase = basename(sourceAbs);\n const sourceExt = extname(sourceBase); // \".atelier\"\n const sourceStem = sourceExt ? sourceBase.slice(0, -sourceExt.length) : sourceBase;\n\n // Collision suffix sequence: -copy, -copy-2, -copy-3, ... (matches CLI\n // canonical). NOTE the gap at -copy-1: the first suffix bump goes straight\n // to -copy-2 because -copy itself is conceptually copy #1.\n let finalStem: string | undefined;\n for (let attempt = 1; attempt <= 999; attempt++) {\n const candidate = attempt === 1 ? `${sourceStem}-copy` : `${sourceStem}-copy-${attempt}`;\n if (!existsSync(join(sourceDir, `${candidate}.atelier`))) {\n finalStem = candidate;\n break;\n }\n }\n if (!finalStem) {\n throw new Error(`duplicateDoc: could not find a non-colliding stem for \"${sourceStem}-copy\"`);\n }\n\n const newDocAbsPath = join(sourceDir, `${finalStem}.atelier`);\n\n // Project-relative new path — preserves the source's parent dir.\n const sourceRel = opts.sourceDocPath;\n const lastSlash = sourceRel.lastIndexOf(\"/\");\n const parentRel = lastSlash >= 0 ? sourceRel.slice(0, lastSlash + 1) : \"\";\n const newDocPath = `${parentRel}${finalStem}.atelier`;\n\n // Preserve `doc.name` verbatim on the duplicate. Matches the CLI's\n // canonical behavior — the studio sidebar uses the filename as the display\n // label, so the in-doc `name` does NOT need to track the new stem.\n const dupDoc: AtelierDocument = { ...sourceDoc };\n writeFileSync(newDocAbsPath, JSON.stringify(dupDoc, null, 2), \"utf-8\");\n\n const report: DocDuplicateReport = {\n sourceDocPath: opts.sourceDocPath,\n newDocPath,\n };\n\n // ── Optional SlideRef append ──────────────────────────────────\n if (opts.appendSlideRef) {\n // Guard: appendSlideRef only makes sense when the source is a slide\n // (lives DIRECTLY under `slides/`). Matches the CLI guard exactly —\n // `dirname === \"slides\"`, NOT \"starts with slides/\". A source nested\n // deeper (e.g. `slides/nested/foo.atelier`) is rejected.\n const sourceDirRel = dirname(opts.sourceDocPath);\n if (sourceDirRel !== \"slides\") {\n // Roll back to avoid leaving an orphan.\n try { unlinkSync(newDocAbsPath); } catch { /* best-effort */ }\n throw new Error(\"appendSlideRef requires a slide source\");\n }\n\n const manifestAbs = join(projectDir, \"project.atelier\");\n if (!existsSync(manifestAbs)) {\n throw new Error(\"duplicateDoc: appendSlideRef requested but project.atelier is missing\");\n }\n const manifest = readAtelierDoc(manifestAbs);\n if (manifest.kind !== \"carousel\") {\n throw new Error(`duplicateDoc: appendSlideRef requires a carousel manifest (kind=${manifest.kind ?? \"video\"})`);\n }\n\n // SlideRef src basis is projectDir; for the manifest at the project root\n // `dirname(manifestAbs) === projectDir` so this matches both the canonical\n // dual-base resolver's preferred basis and the existing CLI behavior.\n const slideSrc = relative(projectDir, newDocAbsPath).split(\"\\\\\").join(\"/\");\n const slides = manifest.slides ?? [];\n if (slides.some((s) => s.src === slideSrc)) {\n throw new Error(`duplicateDoc: slide ${slideSrc} already exists in carousel`);\n }\n\n // Find the source's index in slides[] so we can insert the duplicate\n // adjacent (right after source). Matches the CLI's canonical behavior.\n // Falls back to append if the source isn't currently in slides[].\n const sourceSlideSrc = relative(projectDir, sourceAbs).split(\"\\\\\").join(\"/\");\n const sourceIndex = slides.findIndex((s) => s.src === sourceSlideSrc);\n const insertAt = sourceIndex >= 0 ? sourceIndex + 1 : slides.length;\n\n const newSlide: SlideRef = { src: slideSrc };\n const newSlides = [...slides.slice(0, insertAt), newSlide, ...slides.slice(insertAt)];\n const updatedManifest: AtelierDocument = { ...manifest, slides: newSlides };\n\n writeFileSync(manifestAbs, JSON.stringify(updatedManifest, null, 2), \"utf-8\");\n report.appendedSlideIndex = insertAt;\n }\n\n return report;\n}\n\n// ─── deleteDoc ───────────────────────────────────────────────────────\n\n/**\n * Delete an `.atelier` doc inside a project. Cascades:\n * - Walks every project under `workspaceDir`. For each project, scans\n * EVERY `.atelier` file (manifest + root docs + `slides/*`) for both:\n * * SlideRefs whose resolved src points at the deleted doc — these\n * are scrubbed (spliced out) and reported in `slideRefsRemoved`.\n * * RefVisual layers (`visual.type === \"ref\"`) whose src points at\n * the deleted doc — reported as dangling in `refLayersDangling`\n * with the accurate per-match docPath. NOT auto-removed (the\n * renderer tolerates missing refs; the studio surfaces warnings).\n * - Unlinks the doc file last.\n *\n * Post-pivot: there is no special \"manifest\" guard — `project.atelier` is\n * just another `.atelier` doc and can be deleted like any other.\n */\nexport function deleteDoc(opts: DeleteDocOptions): DocDeleteCascadeReport {\n const workspaceDir = resolve(opts.workspaceDir);\n const projectDir = join(workspaceDir, opts.projectName);\n const docAbs = join(projectDir, opts.docPath);\n\n if (!existsSync(docAbs)) {\n throw new Error(`deleteDoc: doc not found: ${opts.docPath}`);\n }\n\n const report: DocDeleteCascadeReport = {\n docPath: opts.docPath,\n slideRefsRemoved: [],\n refLayersDangling: [],\n };\n\n // ── Workspace walk: every immediate subdir of workspaceDir with a\n // project.atelier is a project candidate.\n let projectNames: string[] = [];\n try {\n projectNames = readdirSync(workspaceDir).filter((entry) => {\n if (entry.startsWith(\".\")) return false;\n try {\n const projDir = join(workspaceDir, entry);\n if (!statSync(projDir).isDirectory()) return false;\n return existsSync(join(projDir, \"project.atelier\"));\n } catch {\n return false;\n }\n });\n } catch {\n projectNames = [];\n }\n\n for (const projName of projectNames) {\n const projDir = join(workspaceDir, projName);\n\n // Walk every .atelier in this project: root docs + slides/*.atelier.\n const projectAtelierFiles = listAtelierFilesUnderProject(projDir);\n\n for (const atelierAbs of projectAtelierFiles) {\n let doc: AtelierDocument;\n try {\n doc = readAtelierDoc(atelierAbs);\n } catch {\n continue;\n }\n let mutated = false;\n const docRel = relative(projDir, atelierAbs).split(\"\\\\\").join(\"/\");\n\n // ── SlideRef scrub (any carousel doc, not just project.atelier) ──\n if (doc.kind === \"carousel\" && Array.isArray(doc.slides)) {\n const keptSlides: SlideRef[] = [];\n doc.slides.forEach((slide, idx) => {\n const slideAbs = resolveRefSrc(slide.src, atelierAbs, projDir, workspaceDir);\n if (slideAbs === docAbs) {\n report.slideRefsRemoved.push({ project: projName, slideIndex: idx });\n mutated = true;\n return;\n }\n keptSlides.push(slide);\n });\n if (mutated) {\n doc = { ...doc, slides: keptSlides };\n }\n }\n\n // ── RefVisual dangling scan (any .atelier) ───────────────\n if (Array.isArray(doc.layers)) {\n for (const layer of doc.layers as Layer[]) {\n const v = layer.visual as Layer[\"visual\"] | undefined;\n if (!v || (v as { type?: string }).type !== \"ref\") continue;\n const refV = v as RefVisual;\n if (typeof refV.src !== \"string\" || !refV.src) continue;\n const refAbs = resolveRefSrc(refV.src, atelierAbs, projDir, workspaceDir);\n if (refAbs === docAbs) {\n report.refLayersDangling.push({\n project: projName,\n docPath: docRel,\n layerId: layer.id,\n });\n }\n }\n }\n\n if (mutated) {\n writeFileSync(atelierAbs, JSON.stringify(doc, null, 2), \"utf-8\");\n }\n }\n }\n\n // ── Unlink the doc itself last (after the cascade) ───────────\n unlinkSync(docAbs);\n\n return report;\n}\n\n/**\n * Enumerate `.atelier` files under a project: every `.atelier` at the\n * project root, plus everything immediately inside `slides/`. Deeper\n * nesting is NOT walked (matches `listDocs`'s posture).\n *\n * Defense-in-depth: filters to regular files via `isFile()` (so directories\n * like `.atelier/` — the paradigm metadata dir — never sneak in) AND skips\n * the literal `.atelier` entry name explicitly.\n */\nfunction listAtelierFilesUnderProject(projectDir: string): string[] {\n const out: string[] = [];\n\n // Root-level .atelier files (manifest + compose targets + any sibling docs).\n try {\n for (const entry of readdirSync(projectDir)) {\n if (entry === \".atelier\") continue; // skip paradigm metadata dir\n if (!entry.endsWith(\".atelier\")) continue;\n const abs = join(projectDir, entry);\n try {\n if (statSync(abs).isFile()) out.push(abs);\n } catch { /* skip */ }\n }\n } catch { /* skip */ }\n\n // slides/*.atelier (one level deep only).\n const slidesDir = join(projectDir, \"slides\");\n if (existsSync(slidesDir)) {\n try {\n for (const entry of readdirSync(slidesDir)) {\n if (!entry.endsWith(\".atelier\")) continue;\n const abs = join(slidesDir, entry);\n try {\n if (statSync(abs).isFile()) out.push(abs);\n } catch { /* skip */ }\n }\n } catch { /* skip */ }\n }\n\n return out;\n}\n\n/**\n * Resolve a SlideRef.src (or RefVisual.src) using the dual-base pattern from\n * `#ref-cycle`: try the doc's owning project dir first (project-relative\n * srcs), then fall back to the workspace root (workspace-relative srcs).\n * Absolute refs are short-circuited via `existsSync`. Returns the absolute\n * resolved path or undefined when neither candidate exists on disk.\n */\nfunction resolveRefSrc(\n src: string,\n currentDocAbs: string,\n ownerProjectDir: string,\n workspaceRoot: string,\n): string | undefined {\n if (isAbsolute(src)) {\n return existsSync(src) ? resolve(src) : undefined;\n }\n // Primary: project-relative (matches the createDoc/duplicateDoc src basis).\n const projectRelative = resolve(ownerProjectDir, src);\n if (existsSync(projectRelative)) return projectRelative;\n // Fallback: relative to the carousel doc's own directory (legacy basis\n // before the projectDir-basis alignment).\n const docRelative = resolve(dirname(currentDocAbs), src);\n if (existsSync(docRelative)) return docRelative;\n // Last resort: workspace-relative srcs.\n const workspaceRelative = resolve(workspaceRoot, src);\n if (existsSync(workspaceRelative)) return workspaceRelative;\n return undefined;\n}\n\n// ─── listDocs ───────────────────────────────────────────────────────\n\n/**\n * Enumerate every `.atelier` doc inside a project for the studio sidebar.\n *\n * Pure filesystem walk: project root + `slides/` (no recursion deeper). Does\n * NOT follow `slides[]` references — slide refs may point anywhere in the\n * workspace, but `listDocs` only reports docs that physically live in THIS\n * project's subtree (root or `slides/`). Carousel refs pointing into other\n * projects surface when THOSE projects are queried.\n *\n * Result is flat alphabetical (by project-relative path), and each entry\n * carries just `{ path, kind? }` — no `role`, no `slideIndex`, no\n * `slideLabel` (those were the pre-pivot manifest-centric fields).\n */\nexport function listDocs(projectDir: string): DocListEntry[] {\n const projAbs = resolve(projectDir);\n const collected: Array<{ rel: string; abs: string }> = [];\n\n // Root-level .atelier files.\n try {\n for (const entry of readdirSync(projAbs)) {\n if (entry === \".atelier\") continue; // skip paradigm metadata dir\n if (!entry.endsWith(\".atelier\")) continue;\n const abs = join(projAbs, entry);\n try {\n if (!statSync(abs).isFile()) continue;\n } catch {\n continue;\n }\n collected.push({ rel: entry, abs });\n }\n } catch { /* skip */ }\n\n // slides/*.atelier (one level deep).\n const slidesDir = join(projAbs, \"slides\");\n if (existsSync(slidesDir)) {\n try {\n for (const entry of readdirSync(slidesDir)) {\n if (!entry.endsWith(\".atelier\")) continue;\n const abs = join(slidesDir, entry);\n try {\n if (!statSync(abs).isFile()) continue;\n } catch {\n continue;\n }\n collected.push({ rel: `slides/${entry}`, abs });\n }\n } catch { /* skip */ }\n }\n\n // Flat alphabetical sort by project-relative path.\n collected.sort((a, b) => (a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0));\n\n const out: DocListEntry[] = [];\n for (const { rel, abs } of collected) {\n let kind: \"video\" | \"image\" | \"carousel\" | undefined;\n try {\n kind = readAtelierDoc(abs).kind;\n } catch { /* skip — entry surfaces with kind undefined */ }\n const entry: DocListEntry = { path: rel };\n if (kind !== undefined) entry.kind = kind;\n out.push(entry);\n }\n\n // Note on cross-project containment (Judge flag item 7): N/A under the\n // pure FS-walk model. Since we never follow slide refs, there are no\n // out-of-project paths to filter. The CLI's containment check is needed\n // there because the CLI's listDocs still walks slides[]; this version\n // doesn't.\n\n return out;\n}\n","// #mcp-lib-doc-management-types — type contracts for the doc-management bundle.\n//\n// **Intentional duplication** of `packages/cli/src/lib/doc-management-types.ts`.\n// MCP cannot import from `@a-company/atelier` (the CLI package) because\n// `cli → mcp` already runs in the dep graph — re-importing back would close\n// the cycle. The same duplication convention is used by clips.ts,\n// rename-media.ts, and timeline-ops.ts (all carry this header).\n//\n// If the canonical types in cli/lib/doc-management-types.ts change, this file\n// MUST be kept in sync — there is no shared package between mcp and cli for\n// these primitives in v1.0. Lifting to a shared package (e.g.\n// `atelier-doc-management`) is tracked as a Unit-0.5 follow-up.\n\nexport type DocKind = \"video\" | \"image\" | \"carousel\";\n\nexport interface CreateDocOptions {\n projectDir: string; // absolute\n name: string;\n kind: DocKind;\n asCarouselSlide?: boolean;\n carouselDocPath?: string;\n insertAt?: number;\n}\n\nexport interface DuplicateDocOptions {\n projectDir: string;\n sourceDocPath: string;\n appendSlideRef?: boolean;\n}\n\nexport interface DeleteDocOptions {\n workspaceDir: string;\n projectName: string;\n docPath: string;\n}\n\nexport interface DocListEntry {\n path: string;\n kind?: \"video\" | \"image\" | \"carousel\";\n}\n\nexport interface DocDeleteCascadeReport {\n docPath: string;\n slideRefsRemoved: Array<{ project: string; slideIndex: number }>;\n refLayersDangling: Array<{ project: string; docPath: string; layerId: string }>;\n}\n\nexport interface DocDuplicateReport {\n sourceDocPath: string;\n newDocPath: string;\n appendedSlideIndex?: number;\n}\n\n/**\n * Aegis surface — see cli/lib/doc-management-types.ts for the long-form spec.\n * Rejects: empty / whitespace-only, leading dot, `/` `\\` or `..` substring,\n * control bytes (NUL through 0x1f), longer than 200 chars.\n */\nexport function isValidDocName(name: unknown): name is string {\n if (typeof name !== \"string\") return false;\n const trimmed = name.trim();\n if (trimmed.length === 0) return false;\n if (trimmed.length > 200) return false;\n if (trimmed.startsWith(\".\")) return false;\n if (trimmed.includes(\"/\") || trimmed.includes(\"\\\\\") || trimmed.includes(\"..\")) return false;\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f]/.test(trimmed)) return false;\n return true;\n}","// @a-company/atelier-mcp — Bridge protocol (LLM↔human live-mutation envelopes)\n//\n// Shared envelope types for the WebSocket bridge that connects an external\n// MCP client (e.g. Claude Desktop running with `atelier-mcp`) to the\n// browser-side AtelierStudio running inside `atelier studio`.\n//\n// The mutation loop is:\n//\n// LLM tool call ──► MCP server ──► DocumentStore.set(source:\"llm\")\n// │\n// ▼\n// DocumentStore.onChange fires\n// │\n// ▼\n// WS bridge broadcasts `llm:mutation`\n// │\n// ▼\n// Browser studio.applyMutation(op)\n// │\n// ▼\n// Canvas re-renders + toast attribution\n// (Cmd-Z still works — history snapshot)\n//\n// Human edit ──► browser AtelierStudio\n// │\n// ▼\n// onDocumentChange ──► `doc:patch` envelope\n// │\n// ▼\n// WS bridge writes DocumentStore.set(source:\"human\")\n// │\n// ▼\n// onChange filter SKIPS broadcast\n// (otherwise the browser would echo itself)\n//\n// v1 ships whole-document replacement so the envelope stays trivial.\n// JSON-patch op shape is v1.1 once we measure the byte cost on real docs.\n\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\n\n/**\n * Who triggered a mutation. Mirrors `DocumentStore.MutationSource` so the\n * tag travels end-to-end without translation between the server-side\n * store and the browser-side Studio.\n */\nexport type MutationSource = \"human\" | \"llm\" | \"system\";\n\n/** Wire-format protocol version. Bump on any breaking envelope change. */\nexport const BRIDGE_PROTOCOL_VERSION = 1 as const;\n\n/**\n * Server-sent on each new bridge client connection. Carries a generated\n * client id and the negotiated protocol version. The client uses this to\n * detect mismatched bridge versions.\n */\nexport interface HelloEnvelope {\n type: \"hello\";\n clientId: string;\n protocolVersion: typeof BRIDGE_PROTOCOL_VERSION;\n}\n\n/**\n * Client → server explicit load request. v1 sends `doc:loaded` proactively\n * on connect so this is reserved for future multi-doc sessions; included\n * now to lock the envelope shape.\n */\nexport interface DocLoadEnvelope {\n type: \"doc:load\";\n documentId: string;\n}\n\n/**\n * Server → client: here is the current state of the document.\n * Sent on connect (after `hello`) and on document switch.\n */\nexport interface DocLoadedEnvelope {\n type: \"doc:loaded\";\n documentId: string;\n doc: AtelierDocument;\n}\n\n/**\n * Client → server: I (the human) just made an edit. The server writes this\n * into the DocumentStore with `source:\"human\"` so the onChange filter does\n * NOT echo it back as `llm:mutation`.\n */\nexport interface DocPatchEnvelope {\n type: \"doc:patch\";\n documentId: string;\n doc: AtelierDocument;\n source: MutationSource;\n /** Optional correlation id so the client can match an ack/error response. */\n opId?: string;\n}\n\n/**\n * Server → client: an LLM (or system source) mutated the document.\n * The browser translates this to `studio.applyMutation({type:\"doc:replace\", doc, source})`.\n */\nexport interface LlmMutationEnvelope {\n type: \"llm:mutation\";\n documentId: string;\n doc: AtelierDocument;\n source: MutationSource;\n /** Name of the MCP tool that triggered the mutation, when known. */\n toolName?: string;\n /** Optional correlation id (mirrors any client-side request id). */\n opId?: string;\n}\n\n/** Generic error envelope, in either direction. */\nexport interface ErrorEnvelope {\n type: \"error\";\n code: string;\n message: string;\n opId?: string;\n}\n\n// ─── Workspace-aware envelopes ─────────────────────────────────────\n//\n// These are server → client only. They let the workspace-aware studio UI\n// react to backend events (media ingest progress, file additions) without\n// polling. The browser side accepts unknown envelope types gracefully, so a\n// older client connected to a newer server is harmless.\n\n/**\n * The media file list on disk changed (file added/removed). The client\n * refetches `/api/project/:name/media` on receipt. Cheap signal — no payload\n * beyond the project name keeps the envelope small for high-frequency events.\n */\nexport interface MediaListChangedEnvelope {\n type: \"media:list:changed\";\n projectName: string;\n}\n\n/** A transcript file was added or updated. */\nexport interface TranscriptAddedEnvelope {\n type: \"transcript:added\";\n projectName: string;\n /** Workspace-relative path of the transcript file. */\n transcriptPath: string;\n}\n\n/**\n * Progress envelope for the multi-step ingest pipeline. `phase` reflects the\n * current sub-step; the UI maps it to a human-readable status string. The\n * `received`/`total` pair carries download progress when phase is\n * `model:download` (whisper model fetch on first use).\n */\nexport interface MediaIngestProgressEnvelope {\n type: \"media:ingest:progress\";\n projectName: string;\n /** Source-file basename for display. */\n file: string;\n phase:\n | \"start\"\n | \"model:download\"\n | \"transcribing\"\n | \"composing\"\n | \"done\"\n | \"error\";\n /** Bytes received so far (download-only). */\n received?: number;\n /** Total bytes when known (download-only). */\n total?: number | null;\n /** Error message when phase === \"error\". */\n error?: string;\n /**\n * Bin-add fields (v1.0 media-bin pivot). Present on `phase: \"done\"`\n * envelopes that came from a no-target ingest. The browser's ToastHost\n * discriminates bin-add from target-drop completion by checking\n * `mediaPath && !targetDocPath`.\n */\n mediaPath?: string;\n fileKind?: \"video\" | \"image\" | \"audio\";\n transcribePending?: boolean;\n /** Set on target-drop progress to differentiate from bin-add envelopes. */\n targetDocPath?: string;\n}\n\n/**\n * A single workspace file was deleted via DELETE /api/file. Used for plain\n * artifacts / sidecar notes / per-file transcripts (anything that the UI\n * surfaces but that isn't the cascade-bearing media-file or whole-project\n * delete). Lets the sidebar invalidate just the affected section.\n *\n * `projectName` is best-effort: when the deleted path lives inside a project\n * subdir the server fills it so the sidebar can `refreshProject(name)`\n * without re-deriving the owner. Workspace-root files (rare) leave it null.\n */\nexport interface FileDeletedEnvelope {\n type: \"file:deleted\";\n /** Workspace-relative path of the removed file. */\n path: string;\n /** Owning project subdir name, when the path is inside a project. */\n projectName: string | null;\n}\n\n/**\n * A media file was deleted via DELETE /api/project/:name/media. Carries the\n * cascade report so the sidebar can refresh both the media list and the\n * transcripts list in one round-trip. See `delete-cascade-project-atelier-surgery`.\n */\nexport interface MediaDeletedEnvelope {\n type: \"media:deleted\";\n projectName: string;\n /** Basename of the deleted media file (e.g. \"IMG_7347.MOV\"). */\n file: string;\n}\n\n/**\n * A whole project was deleted via DELETE /api/project/:name. The sidebar\n * removes it from the projects list; `wasActive` lets the UI clear the\n * active-project indicator when the deleted project happened to be active\n * (the server already cleared active.yaml — this is just the UI signal).\n */\nexport interface ProjectDeletedEnvelope {\n type: \"project:deleted\";\n /** Subdir basename of the removed project. */\n projectName: string;\n /** True iff the deleted project was active (active.yaml was cleared too). */\n wasActive: boolean;\n}\n\n// ── doc:list:changed envelope (v1.0.x doc-management) ──────\n//\n// Server → client signal that the set of .atelier docs inside a project\n// changed (create / duplicate / delete). Mirrors `media:list:changed` —\n// cheap envelope, no payload beyond the project name. Client refetches\n// `GET /api/project/:name/docs` on receipt. The browser tolerates unknown\n// envelope types, so an older client connected to a newer server is\n// harmless. Marker block kept narrow to avoid stomping on Kit-B's edits to\n// `bridge-protocol.ts` from the parallel MCP build.\nexport interface DocListChangedEnvelope {\n type: \"doc:list:changed\";\n /** Subdir basename of the project whose docs[] changed. Client refetches GET /api/project/:name/docs. */\n projectName: string;\n}\n\n/** Discriminated union of all envelopes carried over the bridge. */\nexport type BridgeEnvelope =\n | HelloEnvelope\n | DocLoadEnvelope\n | DocLoadedEnvelope\n | DocPatchEnvelope\n | LlmMutationEnvelope\n | ErrorEnvelope\n | MediaListChangedEnvelope\n | TranscriptAddedEnvelope\n | MediaIngestProgressEnvelope\n | FileDeletedEnvelope\n | MediaDeletedEnvelope\n | ProjectDeletedEnvelope\n | DocListChangedEnvelope;\n\n/** Type guard for runtime envelope validation. */\nexport function isBridgeEnvelope(value: unknown): value is BridgeEnvelope {\n if (!value || typeof value !== \"object\") return false;\n const t = (value as { type?: unknown }).type;\n return (\n t === \"hello\" ||\n t === \"doc:load\" ||\n t === \"doc:loaded\" ||\n t === \"doc:patch\" ||\n t === \"llm:mutation\" ||\n t === \"error\" ||\n t === \"media:list:changed\" ||\n t === \"transcript:added\" ||\n t === \"media:ingest:progress\" ||\n t === \"file:deleted\" ||\n t === \"media:deleted\" ||\n t === \"project:deleted\" ||\n t === \"doc:list:changed\"\n );\n}\n","// @a-company/atelier-mcp — WebSocket server transport for the MCP SDK\n//\n// Wraps a single WebSocket (from the `ws` library) as an MCP Transport so\n// the same `McpServer` from `createServer()` can be reached over `/mcp` on\n// the `atelier studio` Hono-equivalent (Vite-backed) HTTP server.\n//\n// Used in tandem with the live bridge in `bridge-protocol.ts`:\n// - MCP over /mcp → external client drives DocumentStore mutations.\n// - Bridge over /bridge → broadcasts those mutations into the browser\n// studio so the human sees them land in real time.\n//\n// Per-connection instance: one transport per WebSocket. The CLI spawns a\n// new `McpServer` per connection but shares the underlying `DocumentStore`\n// across all of them so mutations from any client surface through the\n// single onChange emitter the bridge subscribes to.\n\nimport type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { WebSocket as WsWebSocket } from \"ws\";\n\n/** Minimal slice of `ws.WebSocket` we depend on — keeps the transport mockable. */\nexport interface WsLike {\n readyState: number;\n send(data: string): void;\n close(): void;\n on(event: \"message\", listener: (data: unknown) => void): void;\n on(event: \"close\", listener: () => void): void;\n on(event: \"error\", listener: (err: Error) => void): void;\n off?(event: string, listener: (...args: unknown[]) => void): void;\n}\n\n/**\n * MCP server transport over a single WebSocket connection.\n *\n * Lifecycle:\n * 1. CLI accepts WS upgrade, instantiates `new WebSocketServerTransport(ws)`.\n * 2. CLI passes it to `server.connect(transport)` — the SDK then calls\n * `start()` and wires `onmessage` / `send()`.\n * 3. Incoming WS frames → parsed as JSON-RPC → `onmessage(message)`.\n * 4. SDK `send(message)` → JSON.stringify → `ws.send(...)`.\n * 5. WS `close` → `onclose()` fires once.\n *\n * Parse errors on inbound frames are surfaced via `onerror()` but do NOT\n * close the connection — a malformed message from a misbehaving client\n * should not knock out a healthy session.\n */\nexport class WebSocketServerTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n sessionId?: string;\n\n private started = false;\n private closed = false;\n\n constructor(private readonly ws: WsLike) {}\n\n async start(): Promise<void> {\n if (this.started) {\n throw new Error(\n \"WebSocketServerTransport already started — the MCP SDK calls start() automatically; do not call it again\",\n );\n }\n this.started = true;\n\n this.ws.on(\"message\", (data: unknown) => {\n // `ws` delivers Buffer / ArrayBuffer / Buffer[] depending on frame type.\n // Normalize to string before JSON.parse.\n let text: string;\n try {\n if (typeof data === \"string\") {\n text = data;\n } else if (data instanceof Buffer) {\n text = data.toString(\"utf-8\");\n } else if (Array.isArray(data)) {\n text = Buffer.concat(data as Buffer[]).toString(\"utf-8\");\n } else if (data instanceof ArrayBuffer) {\n text = Buffer.from(data).toString(\"utf-8\");\n } else {\n text = String(data);\n }\n } catch (err) {\n this.onerror?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch (err) {\n this.onerror?.(\n new Error(\n `WebSocketServerTransport: failed to parse JSON-RPC message: ${\n err instanceof Error ? err.message : String(err)\n }`,\n ),\n );\n return;\n }\n\n // The SDK validates message shape downstream; we just hand it the parsed value.\n this.onmessage?.(parsed as JSONRPCMessage);\n });\n\n this.ws.on(\"close\", () => {\n if (this.closed) return;\n this.closed = true;\n this.onclose?.();\n });\n\n this.ws.on(\"error\", (err: Error) => {\n this.onerror?.(err);\n });\n }\n\n async send(message: JSONRPCMessage): Promise<void> {\n if (this.closed) {\n throw new Error(\"WebSocketServerTransport: cannot send after close\");\n }\n // ws.WebSocket.OPEN === 1. Hard-coded to avoid importing ws at top level\n // (keeps the test seam clean — WsLike can be a plain object with readyState).\n if (this.ws.readyState !== 1) {\n throw new Error(\n `WebSocketServerTransport: WebSocket is not OPEN (readyState=${this.ws.readyState})`,\n );\n }\n this.ws.send(JSON.stringify(message));\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n try {\n this.ws.close();\n } catch {\n // Swallow — close() should be idempotent and never throw.\n }\n this.onclose?.();\n }\n}\n\n/** Re-export the imported `ws.WebSocket` type for downstream consumers. */\nexport type { WsWebSocket };\n"],"mappings":"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","names":["z","z","yamlParse","yamlStringify","err","z","z","z","z","z","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","z","getDoc","ok","err","AnimatablePropertyEnum","EasingInputSchema","PresetDeltaSchema","z","register","z","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","getDoc","ok","err","EasingInputSchema","register","z","colorToCSS","r","g","b","a","isExpression","kfs","buildTransform","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","getDoc","ok","err","register","z","z","getDoc","ok","err","register","z","getDoc","ok","err","DEFAULT_OVERLAY_MARGIN","anchorToFrame","renderPageNumberFormat","register","z","existsSync","readdirSync","resolve","join","z","getDoc","ok","err","register","existsSync","statSync","readdirSync","resolve","join","basename","extname","z","ok","err","join","existsSync","statSync","readdirSync","register","z","resolve","extname","basename","existsSync","readFileSync","statSync","readdirSync","join","resolve","z","ok","err","register","existsSync","readFileSync","statSync","writeFileSync","join","resolve","z","parseYaml","stringifyYaml","ok","err","resolve","existsSync","statSync","join","readFileSync","parseYaml","stringifyYaml","writeFileSync","register","z","existsSync","readFileSync","writeFileSync","basename","extname","isAbsolute","join","resolve","z","basename","extname","ok","err","resolve","join","existsSync","readFileSync","writeFileSync","isAbsolute","basename","register","z","stripExt","extname","z","existsSync","readFileSync","writeFileSync","extname","join","resolve","readFileSync","stripExt","extname","out","join","existsSync","resolve","err","writeFileSync","existsSync","readFileSync","join","resolve","register","z","z","existsSync","readFileSync","join","resolve","sep","existsSync","mkdirSync","readdirSync","readFileSync","statSync","writeFileSync","basename","dirname","extname","isAbsolute","join","resolve","slugifyBasename","readAtelierDoc","readFileSync","resolve","join","existsSync","mkdirSync","dirname","writeFileSync","basename","extname","readdirSync","statSync","isAbsolute","resolve","sep","readFileSync","register","z","existsSync","join","err","register"]}