@things-factory/board-ai 10.1.24 β 10.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PLAN-styling-tools.md +1 -1
- package/dist-client/server/service/assistant.d.ts +5 -4
- package/dist-client/server/service/assistant.js +35 -35
- package/dist-client/server/service/assistant.js.map +1 -1
- package/dist-client/server/service/styling/clear-tools.d.ts +2 -2
- package/dist-client/server/service/styling/clear-tools.js.map +1 -1
- package/dist-client/server/service/styling/copy-tools.d.ts +3 -3
- package/dist-client/server/service/styling/copy-tools.js +1 -1
- package/dist-client/server/service/styling/copy-tools.js.map +1 -1
- package/dist-client/server/service/styling/effect-tools.d.ts +2 -2
- package/dist-client/server/service/styling/effect-tools.js.map +1 -1
- package/dist-client/server/service/styling/fill-tools.d.ts +3 -3
- package/dist-client/server/service/styling/fill-tools.js +1 -1
- package/dist-client/server/service/styling/fill-tools.js.map +1 -1
- package/dist-client/server/service/styling/material-tools.d.ts +2 -2
- package/dist-client/server/service/styling/material-tools.js.map +1 -1
- package/dist-client/server/service/styling/registry.d.ts +6 -6
- package/dist-client/server/service/styling/registry.js +2 -2
- package/dist-client/server/service/styling/registry.js.map +1 -1
- package/dist-client/server/service/styling/stroke-tools.d.ts +2 -2
- package/dist-client/server/service/styling/stroke-tools.js.map +1 -1
- package/dist-client/server/service/styling/text-tools.d.ts +2 -2
- package/dist-client/server/service/styling/text-tools.js.map +1 -1
- package/dist-client/server/service/types.d.ts +6 -148
- package/dist-client/server/service/types.js.map +1 -1
- package/dist-client/server/service/validation/board-model-schema.d.ts +262 -262
- package/dist-client/server/service/validation/board-model-schema.js +4 -4
- package/dist-client/server/service/validation/board-model-schema.js.map +1 -1
- package/dist-client/server/service/validation/tool-validation.js +5 -5
- package/dist-client/server/service/validation/tool-validation.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/index.d.ts +2 -2
- package/dist-server/index.js +2 -2
- package/dist-server/index.js.map +1 -1
- package/dist-server/service/assistant.d.ts +5 -4
- package/dist-server/service/assistant.js +37 -37
- package/dist-server/service/assistant.js.map +1 -1
- package/dist-server/service/board-ai-resolver.js +2 -2
- package/dist-server/service/board-ai-resolver.js.map +1 -1
- package/dist-server/service/index.d.ts +0 -1
- package/dist-server/service/index.js +0 -1
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/patch-entry/board-patch-subscription.js +1 -1
- package/dist-server/service/patch-entry/board-patch-subscription.js.map +1 -1
- package/dist-server/service/patch-entry/patch-entry.d.ts +1 -1
- package/dist-server/service/patch-entry/patch-entry.js +1 -1
- package/dist-server/service/patch-entry/patch-entry.js.map +1 -1
- package/dist-server/service/styling/clear-tools.d.ts +2 -2
- package/dist-server/service/styling/clear-tools.js.map +1 -1
- package/dist-server/service/styling/copy-tools.d.ts +3 -3
- package/dist-server/service/styling/copy-tools.js +1 -1
- package/dist-server/service/styling/copy-tools.js.map +1 -1
- package/dist-server/service/styling/effect-tools.d.ts +2 -2
- package/dist-server/service/styling/effect-tools.js.map +1 -1
- package/dist-server/service/styling/fill-tools.d.ts +3 -3
- package/dist-server/service/styling/fill-tools.js +1 -1
- package/dist-server/service/styling/fill-tools.js.map +1 -1
- package/dist-server/service/styling/material-tools.d.ts +2 -2
- package/dist-server/service/styling/material-tools.js.map +1 -1
- package/dist-server/service/styling/registry.d.ts +6 -6
- package/dist-server/service/styling/registry.js +2 -2
- package/dist-server/service/styling/registry.js.map +1 -1
- package/dist-server/service/styling/stroke-tools.d.ts +2 -2
- package/dist-server/service/styling/stroke-tools.js.map +1 -1
- package/dist-server/service/styling/text-tools.d.ts +2 -2
- package/dist-server/service/styling/text-tools.js.map +1 -1
- package/dist-server/service/types.d.ts +6 -148
- package/dist-server/service/types.js.map +1 -1
- package/dist-server/service/validation/board-model-schema.d.ts +262 -262
- package/dist-server/service/validation/board-model-schema.js +4 -4
- package/dist-server/service/validation/board-model-schema.js.map +1 -1
- package/dist-server/service/validation/tool-validation.js +5 -5
- package/dist-server/service/validation/tool-validation.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +5 -0
- package/logs/connections-2026-09-17-16.log +0 -0
- package/package.json +8 -7
- package/server/index.ts +2 -2
- package/server/service/assistant-integration.test.ts +44 -44
- package/server/service/assistant-llm-smoke.test.ts +5 -5
- package/server/service/assistant.test.ts +86 -86
- package/server/service/assistant.ts +41 -43
- package/server/service/board-ai-resolver.ts +2 -2
- package/server/service/index.ts +0 -1
- package/server/service/patch-entry/board-patch-subscription.ts +1 -1
- package/server/service/patch-entry/patch-entry.ts +2 -2
- package/server/service/styling/clear-tools.ts +2 -2
- package/server/service/styling/copy-tools.ts +3 -3
- package/server/service/styling/effect-tools.ts +2 -2
- package/server/service/styling/fill-tools.test.ts +1 -1
- package/server/service/styling/fill-tools.ts +4 -4
- package/server/service/styling/material-tools.ts +2 -2
- package/server/service/styling/registry.ts +6 -6
- package/server/service/styling/stroke-tools.test.ts +1 -1
- package/server/service/styling/stroke-tools.ts +3 -3
- package/server/service/styling/text-tools.ts +2 -2
- package/server/service/tool-exposure.test.ts +7 -7
- package/server/service/types.ts +9 -110
- package/server/service/validation/board-model-schema.test.ts +3 -3
- package/server/service/validation/board-model-schema.ts +4 -4
- package/server/service/validation/tool-validation.ts +5 -5
- package/dist-server/service/apply-patch.d.ts +0 -47
- package/dist-server/service/apply-patch.js +0 -369
- package/dist-server/service/apply-patch.js.map +0 -1
- package/server/service/apply-patch-drift.test.ts +0 -831
- package/server/service/apply-patch.test.ts +0 -757
- package/server/service/apply-patch.ts +0 -411
|
@@ -309,7 +309,7 @@ exports.ComponentSchema = ComponentBaseSchema.superRefine((component, ctx) => {
|
|
|
309
309
|
* β’ μλ³: id, refid, type
|
|
310
310
|
*
|
|
311
311
|
* β `name` μ things-scene model-layer κ° μΈμ μ ν¨ β Board *μν°ν°* μ 컬λΌμ΄μ§
|
|
312
|
-
* scene MODEL μ νλκ° μλ. AI κ°
|
|
312
|
+
* scene MODEL μ νλκ° μλ. AI κ° modifyScene λ‘ name μ 보λ΄λ μ£½μ νλ. κ²μ¦
|
|
313
313
|
* μμλ μ κ±° / 무μ μ μ±
.
|
|
314
314
|
*
|
|
315
315
|
* `passthrough` μΈ μ΄μ β 3D κ΄μ/μΉ΄λ©λΌ/sky λ± ν€κ° λ무 λ§μ strict λ‘λ νκ· μν
|
|
@@ -354,14 +354,14 @@ exports.ComponentPatchSchema = zod_1.z
|
|
|
354
354
|
})
|
|
355
355
|
.passthrough(); // μμΉ / ν¬κΈ° / μ»΄ν¬λνΈ specific ν΅κ³Ό
|
|
356
356
|
/**
|
|
357
|
-
*
|
|
357
|
+
* modifyScene op μ patch β 보λ root partial.
|
|
358
358
|
*
|
|
359
359
|
* λͺ¨λ root νλ optional (BoardModelSchema μ λ¬λ¦¬ width/height λ optional).
|
|
360
360
|
* passthrough λ‘ μλ €μ§μ§ μμ root ν€ (3D atmosphere, sky, camera λ±) ν΅κ³Ό.
|
|
361
361
|
* λ€λ§ *μλ €μ§ nested object* (fillStyle λ±) λ strict schema μ¬μ¬μ© β κ·Έ μμ
|
|
362
362
|
* unknown key κ° λ€μ΄μ€λ©΄ κ±°λΆ (μ: fillStyle μ gradientStops κ°μ stale μ΄λ¦).
|
|
363
363
|
*
|
|
364
|
-
* AI κ° setFill λ±μμ νμ΅ν vocabulary λ₯Ό
|
|
364
|
+
* AI κ° setFill λ±μμ νμ΅ν vocabulary λ₯Ό modifyScene λ‘ echo μν¬ λ stale
|
|
365
365
|
* key κ° fillStyle / shadow κ°μ sub-object μμ λΌλ©΄ λ³Έ schema κ° catch.
|
|
366
366
|
*/
|
|
367
367
|
exports.BoardPatchSchema = zod_1.z
|
|
@@ -399,7 +399,7 @@ function validateComponent(component) {
|
|
|
399
399
|
return { valid: true };
|
|
400
400
|
return { valid: false, errors: formatIssues(r.error) };
|
|
401
401
|
}
|
|
402
|
-
/**
|
|
402
|
+
/** modifyScene op μ patch κ²μ¦. 보λ root partial. */
|
|
403
403
|
function validateBoardPatch(patch) {
|
|
404
404
|
const r = exports.BoardPatchSchema.safeParse(patch);
|
|
405
405
|
if (r.success)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"board-model-schema.js","sourceRoot":"","sources":["../../../server/service/validation/board-model-schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * BoardModel zod schema β μμ / patch μ μ© boundary μμ λ°μ΄ν° λ¬΄κ²°μ± κ²μ¦.\n *\n * ν΅μ¬ μ μ±
:\n * - things-scene μ μ€μ drawer / setter ꡬνμ μ§μ€λ‘ λ΄ (μΈν°νμ΄μ€ declaration X)\n * - Component schema λ `.passthrough()` β μλ €μ§ νλ κ²μ¦ + λ―Έμ§ νλ ν΅κ³Ό\n * (μ¬μ©μ μ μ / λ°μ΄ν° λ°μΈλ© / μ»΄ν¬λνΈλ³ specific μμ± νμ©)\n * - κ·Έλ¬λ styling sub-objects (FillStyle / Shadow λ±) λ `.strict()` β unknown key\n * κ±°λΆ. stale μμ¬ νλ (μ: colorStops + colors 곡쑴) μλ λ°κ²¬.\n * - validation μ€ν¨ μ silent λλ½ X β caller κ° λͺ
μμ μλ¬ / λ‘κ·Έ\n *\n * μ μ© μ§μ :\n * 1. server `UpdateBoard` mutation μ§μ
β DB μμ μ§μ λ§μ§λ§ λ°©μ΄μ \n * 2. server `BoardAIChat` mutation μλ΅ μ§μ β AI κ° λ§λ patch μ μμ μ±\n * 3. (μ ν) client apply-patch μ μ© ν β λ©λͺ¨λ¦¬ μν 무결μ±\n */\nimport { z } from 'zod'\n\n// ββ Color ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n/**\n * μμ β hex (#rgb / #rgba / #rrggbb / #rrggbbaa) / rgb / rgba / CSS named / 'transparent'.\n * μ κ·μμ λμ¨ β μ νν κ²μ¦μ normalizeColor κ°, μ¬κΈ°μ νμλ§.\n */\nconst ColorSchema = z.string().min(1).max(50)\n\n// ββ FillStyle (state.fillStyle) ββββββββββββββββββββββββββββββββββ\n//\n// μ€μ νμ (drawer/fill.ts κ²μ¦):\n// - solid: μμ string κ·Έλλ‘\n// - gradient: { type: 'gradient', gradientType, colorStops: [{position, color}], rotation?, opacity? }\n// - pattern: { type: 'pattern', image, ...μ΅μ
λ€ }\n// - none: undefined / null\n\nconst GradientStopSchema = z\n .object({\n position: z.number().min(0).max(1),\n color: ColorSchema\n })\n .strict()\n\nconst FillStyleGradientSchema = z\n .object({\n type: z.literal('gradient'),\n gradientType: z.enum(['linear', 'radial']).optional(),\n colorStops: z.array(GradientStopSchema).min(2),\n rotation: z.number().optional(),\n opacity: z.number().min(0).max(1).optional(),\n center: z\n .enum([\n 'center',\n 'left-top',\n 'left-bottom',\n 'right-top',\n 'right-bottom',\n 'left',\n 'right',\n 'top',\n 'bottom'\n ])\n .optional()\n })\n .strict()\n\nconst FillStylePatternSchema = z\n .object({\n type: z.literal('pattern'),\n image: z.union([z.string(), z.unknown()]),\n color: ColorSchema.optional(),\n fitPattern: z.boolean().optional(),\n noRepeat: z.boolean().optional(),\n align: z\n .enum([\n 'center',\n 'left-top',\n 'left-bottom',\n 'right-top',\n 'right-bottom',\n 'left',\n 'right',\n 'top',\n 'bottom'\n ])\n .optional(),\n offsetX: z.number().optional(),\n offsetY: z.number().optional(),\n width: z.number().optional(),\n height: z.number().optional(),\n opacity: z.number().min(0).max(1).optional(),\n guideOnly: z.boolean().optional()\n })\n .strict()\n\n/** 'none' type β fillStyle μ κ±° μλ νν (state.fillStyle = {type:'none'} λ νμ©). */\nconst FillStyleNoneSchema = z.object({ type: z.literal('none') }).strict()\n\nexport const FillStyleSchema = z.union([\n ColorSchema, // solid: '#xxx'\n FillStyleGradientSchema,\n FillStylePatternSchema,\n FillStyleNoneSchema,\n z.null()\n])\n\n// ββ Shadow (state.shadow) ββββββββββββββββββββββββββββββββββββββββ\n//\n// Canonical (CSS box-shadow / Canvas API νμ€): { color, offsetX, offsetY, blur }\n// Backwards-compat aliases (μ μ΄λ¦, drawer κ° fallback μΌλ‘ μ½μ): left / top / blurSize.\n// μμλ μ λ°μ΄ν° νΈνμ μν΄ λ μ΄λ¦ λ€ schema ν΅κ³Ό β μ μ½λλ canonical μ¬μ©.\n\nexport const ShadowSchema = z\n .object({\n color: ColorSchema.optional(),\n // canonical (CSS / Canvas νμ€)\n offsetX: z.number().optional(),\n offsetY: z.number().optional(),\n blur: z.number().min(0).optional(),\n // legacy aliases β μ things-scene λ°μ΄ν° νΈνμ©. μ μ½λλ μ canonical μ¬μ©.\n left: z.number().optional(),\n top: z.number().optional(),\n blurSize: z.number().min(0).optional()\n })\n .strict()\n\n// ββ Material3D (state.material3d) ββββββββββββββββββββββββββββββββ\n//\n// `things-scene/src/threed/material-3d.ts` μ Material3D μΈν°νμ΄μ€μ μΌμΉ.\n\nexport const Material3DSchema = z\n .object({\n preset: z\n .enum(['default', 'metal', 'glass', 'plastic', 'wood', 'ceramic', 'rubber', 'custom'])\n .optional(),\n metalness: z.number().min(0).max(1).optional(),\n roughness: z.number().min(0).max(1).optional(),\n emissive: ColorSchema.optional(),\n emissiveIntensity: z.number().min(0).max(5).optional(),\n opacity: z.number().min(0).max(1).optional(),\n envMapIntensity: z.number().min(0).max(3).optional(),\n side: z.enum(['double', 'front', 'back']).optional(),\n castShadow: z.boolean().optional(),\n receiveShadow: z.boolean().optional()\n })\n .strict()\n\n// ββ DataMapping (state.mappings) βββββββββββββββββββββββββββββββββ\n//\n// λ°μ΄ν° λ°μΈλ© β `interfaces/data.ts` Mapping. rule / target / accessor / converter / param.\n\nexport const MappingSchema = z\n .object({\n rule: z.string().optional(),\n target: z.string(),\n property: z.string().optional(),\n accessor: z.string().optional(),\n source: z.unknown().optional(),\n converter: z.union([z.string(), z.unknown()]).optional(),\n param: z.unknown().optional()\n })\n .passthrough() // mapping μ μμ νλ (converter args λ±) νμ©\n\n// ββ Component (one component in board.components) ββββββββββββββββ\n//\n// ν΅μ¬ styling νλλ λͺ
μ κ²μ¦, λλ¨Έμ§λ passthrough β μ»΄ν¬λνΈλ³ specific μμ± μμ .\n\nconst LineDashSchema = z.enum([\n 'solid',\n 'round-dot',\n 'square-dot',\n 'dash',\n 'dash-dot',\n 'long-dash',\n 'long-dash-dot',\n 'long-dash-dot-dot'\n])\n\n/**\n * μ»΄ν¬λνΈκ° *μ΄λ€ ννλ * μ ν¨ν geometry λ₯Ό κ°μ‘λμ§ νμΈ.\n *\n * things-scene μ μ»΄ν¬λνΈ type λ³λ‘ geometry νλκ° λ€μν¨ (rect λ box,\n * line μ endpoints, polyline μ vertices/path λ±). type β νλ λ§€νμ strict\n * νκ² enumerate νλ©΄ μ κ· type λ±λ‘ μ schema λ λμ μ
λ°μ΄νΈ νμ β forward\n * compatibility μν΄.\n *\n * λμ \"μ΅μν μ΄λ€ geometry νμμ΄λΌλ μμ΄μΌ νλ€\" λ μ½ν 보μ₯ β λΉ μ»΄ν¬λνΈ\n * (`{type:'rect'}` λ§) λλ type μ μ λ§λ geometry κ΅¬μ± (`{type:'rect', cx:10, cy:20}`)\n * κ°μ λͺ
λ°±ν μ€λ₯λ§ μ°¨λ¨. μ€μ λ λλ§ μ ν©μ±μ things-scene μμ²΄κ° κ²μ¦.\n */\nfunction componentHasValidGeometry(component: any): boolean {\n if (!component || typeof component !== 'object') return false\n\n // Box geometry β left/top λ λ€ μμ΄μΌ (width/height λ optional)\n const hasBox = typeof component.left === 'number' && typeof component.top === 'number'\n\n // Circle/ellipse geometry β cx/cy λ λ€ μμ΄μΌ\n const hasCircle = typeof component.cx === 'number' && typeof component.cy === 'number'\n\n // Line endpoints\n const hasLineEndpoints =\n typeof component.x1 === 'number' &&\n typeof component.y1 === 'number' &&\n typeof component.x2 === 'number' &&\n typeof component.y2 === 'number'\n\n // Path / points / vertices κ³μ΄\n const hasPath = typeof component.path === 'string' || Array.isArray(component.path)\n const hasPoints = Array.isArray(component.points) && component.points.length > 0\n const hasVertices =\n (Array.isArray(component.vertices) && component.vertices.length > 0) ||\n (Array.isArray(component.verticles) && component.verticles.length > 0) // legacy μ€ν\n\n // line connector β startPoint / endPoint νν (anchor κΈ°λ° line)\n const hasConnector =\n component.from && typeof component.from === 'object' &&\n component.to && typeof component.to === 'object'\n\n return hasBox || hasCircle || hasLineEndpoints || hasPath || hasPoints || hasVertices || hasConnector\n}\n\n/** type μ΄ 'gauge' λλ 'gauge-*' λ©΄ value νλ νμ (μ ν: min/max). */\nfunction isGaugeType(type: string): boolean {\n return type === 'gauge' || type.startsWith('gauge-')\n}\n\n/** type μ΄ 'chart' λλ 'chart-*' λ©΄ data νλ νμ. */\nfunction isChartType(type: string): boolean {\n return type === 'chart' || type.startsWith('chart-')\n}\n\nconst ComponentBaseSchema = z\n .object({\n type: z.string().min(1),\n refid: z.number().int().optional(), // μ κ· μ»΄ν¬λνΈ μΆκ° μμ μ λ―Έν λΉ κ°λ₯\n // μμΉ / ν¬κΈ° β μ»΄ν¬λνΈ νμ
μ λ°λΌ λ€λ¦. λ³Έ schema λ optional λ‘ λκ³ \n // refinement κ° *μ΄λ€ ννλ * μλμ§λ§ κ²μ¬.\n left: z.number().optional(),\n top: z.number().optional(),\n width: z.number().optional(),\n height: z.number().optional(),\n cx: z.number().optional(),\n cy: z.number().optional(),\n rx: z.number().optional(),\n ry: z.number().optional(),\n radius: z.number().optional(),\n x1: z.number().optional(),\n y1: z.number().optional(),\n x2: z.number().optional(),\n y2: z.number().optional(),\n rotation: z.number().optional(),\n // styling\n fillStyle: FillStyleSchema.optional(),\n strokeStyle: ColorSchema.optional(), // top-level string\n lineWidth: z.number().min(0).optional(),\n lineDash: LineDashSchema.optional(),\n lineCap: z.enum(['butt', 'round', 'square']).optional(),\n lineJoin: z.enum(['miter', 'round', 'bevel']).optional(),\n shadow: ShadowSchema.optional(),\n material3d: Material3DSchema.optional(),\n // text / font β top-level\n text: z.string().optional(),\n fontFamily: z.string().optional(),\n fontSize: z.number().positive().optional(),\n fontWeight: z.union([z.string(), z.number()]).optional(),\n fontStyle: z.string().optional(),\n fontColor: ColorSchema.optional(),\n textAlign: z.enum(['left', 'center', 'right', 'start', 'end', 'justify']).optional(),\n textBaseline: z\n .enum(['top', 'middle', 'bottom', 'hanging', 'alphabetic', 'ideographic'])\n .optional(),\n lineHeight: z.number().positive().optional(),\n // visibility / opacity\n alpha: z.number().min(0).max(1).optional(),\n hidden: z.boolean().optional(),\n // misc β κ²μ¦ μ ν¨\n id: z.string().optional(),\n class: z.string().optional(),\n tag: z.string().optional(),\n // λ°μ΄ν° λ°μΈλ©\n mappings: z.array(MappingSchema).optional()\n })\n .passthrough() // μ»΄ν¬λνΈλ³ specific μμ± (vehicle wheels, gauge needle, points/path λ±) νμ©\n\n/**\n * Component schema β base μμ type-aware refinement λ κ°μ§:\n *\n * 1. λͺ¨λ μ»΄ν¬λνΈλ *μ΄λ€ ννλ * μ ν¨ν geometry κ° μμ΄μΌ\n * (left+top / cx+cy / x1y1x2y2 / path / points / vertices / from+to)\n * 2. gauge-* type μ value νμ, chart-* type μ data νμ (soft check β\n * μΌλΆ prefab μ΄ λ―Έλ¦¬ μ±μμ£Όλ μΌμ΄μ€λ μμ΄ strict κ±°λΆλ³΄λ€ 미리 μ‘κΈ° λͺ©μ )\n *\n * μ΄ refinement λ€μ΄ LLM μ μλͺ»λ geometry (rect μ cx/cyλ§, line μ left/topλ§)\n * λ₯Ό μμ μ§μ μ°¨λ¨.\n */\nexport const ComponentSchema = ComponentBaseSchema.superRefine((component, ctx) => {\n if (!componentHasValidGeometry(component)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n `Component '${component.type}' has no valid geometry β provide left+top (box), cx+cy (circle/ellipse), x1+y1+x2+y2 (line), path / points / vertices, or from+to (connector).`\n })\n }\n\n if (isGaugeType(component.type) && component.value === undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['value'],\n message: `Component '${component.type}' requires 'value' (current sensor reading or display number).`\n })\n }\n\n if (isChartType(component.type) && component.data === undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['data'],\n message: `Component '${component.type}' requires 'data' (chart datapoints array or object).`\n })\n }\n})\n\n// ββ BoardModel (top-level) βββββββββββββββββββββββββββββββββββββββ\n\n/**\n * BoardModel β things-scene μ model-layer (보λ root).\n *\n * μΈμλλ root μμ± (model-layer μ NATURE.properties + μ€μ μ½λμμ state.* λ‘\n * μ°Έμ‘°λλ ν€):\n * β’ Layout: width, height, fitMode, translate, scale\n * β’ 2D λ°°κ²½: fillStyle\n * β’ 3D Sky: sky, skyColor\n * β’ 3D Tone: exposure\n * β’ 3D Hemisphere: hemiSkyColor, hemiGroundColor, hemiIntensity\n * β’ 3D Directional light: dirLightEnabled, dirLightColor, dirLightIntensity,\n * dirLightFollowCamera, dirLightAzimuth, dirLightElevation\n * β’ 3D Shadow: dirShadowEnabled, dirShadowMapSize, dirShadowBias\n * β’ 3D Camera: cameraX, cameraY, cameraZ, cameraAutoPlay, autoRotate, initialCameraView\n * β’ μλ³: id, refid, type\n *\n * β `name` μ things-scene model-layer κ° μΈμ μ ν¨ β Board *μν°ν°* μ 컬λΌμ΄μ§\n * scene MODEL μ νλκ° μλ. AI κ° modifyBoard λ‘ name μ 보λ΄λ μ£½μ νλ. κ²μ¦\n * μμλ μ κ±° / 무μ μ μ±
.\n *\n * `passthrough` μΈ μ΄μ β 3D κ΄μ/μΉ΄λ©λΌ/sky λ± ν€κ° λ무 λ§μ strict λ‘λ νκ· μν\n * νΌ. λμ ν¨ν€μ§ μΈλΆ (operato λ±) κ° μμ root ν€ μΆκ°νλ κ±Έ λ§μ§ μμ.\n */\nexport const BoardModelSchema = z\n .object({\n width: z.number().positive(),\n height: z.number().positive(),\n fillStyle: FillStyleSchema.optional(), // 보λ λ°°κ²½\n components: z.array(ComponentSchema).optional()\n })\n .passthrough() // 보λ λ 벨 μμ νλ (3D atmosphere / sky / camera λ±)\n\n// ββ Patch op schemas β modify op μ patch κ° invalid μ΄λ©΄ κ±°λΆ βββ\n\n/**\n * modify op μ patch β μ»΄ν¬λνΈ partial. λͺ¨λ νλ optional. styling sub-object\n * λ§ strict νκ² κ²μ¦ν΄ stale key μμ‘΄ μ°¨λ¨.\n */\nexport const ComponentPatchSchema = z\n .object({\n fillStyle: FillStyleSchema.nullable().optional(),\n strokeStyle: ColorSchema.nullable().optional(),\n lineWidth: z.number().min(0).optional(),\n lineDash: LineDashSchema.optional(),\n lineCap: z.enum(['butt', 'round', 'square']).optional(),\n lineJoin: z.enum(['miter', 'round', 'bevel']).optional(),\n shadow: ShadowSchema.nullable().optional(),\n material3d: Material3DSchema.nullable().optional(),\n text: z.string().optional(),\n fontFamily: z.string().optional(),\n fontSize: z.number().positive().optional(),\n fontWeight: z.union([z.string(), z.number()]).optional(),\n fontStyle: z.string().optional(),\n fontColor: ColorSchema.optional(),\n textAlign: z.enum(['left', 'center', 'right', 'start', 'end', 'justify']).optional(),\n textBaseline: z\n .enum(['top', 'middle', 'bottom', 'hanging', 'alphabetic', 'ideographic'])\n .optional(),\n lineHeight: z.number().positive().optional(),\n alpha: z.number().min(0).max(1).optional(),\n hidden: z.boolean().optional()\n })\n .passthrough() // μμΉ / ν¬κΈ° / μ»΄ν¬λνΈ specific ν΅κ³Ό\n\n/**\n * modifyBoard op μ patch β 보λ root partial.\n *\n * λͺ¨λ root νλ optional (BoardModelSchema μ λ¬λ¦¬ width/height λ optional).\n * passthrough λ‘ μλ €μ§μ§ μμ root ν€ (3D atmosphere, sky, camera λ±) ν΅κ³Ό.\n * λ€λ§ *μλ €μ§ nested object* (fillStyle λ±) λ strict schema μ¬μ¬μ© β κ·Έ μμ\n * unknown key κ° λ€μ΄μ€λ©΄ κ±°λΆ (μ: fillStyle μ gradientStops κ°μ stale μ΄λ¦).\n *\n * AI κ° setFill λ±μμ νμ΅ν vocabulary λ₯Ό modifyBoard λ‘ echo μν¬ λ stale\n * key κ° fillStyle / shadow κ°μ sub-object μμ λΌλ©΄ λ³Έ schema κ° catch.\n */\nexport const BoardPatchSchema = z\n .object({\n width: z.number().positive().optional(),\n height: z.number().positive().optional(),\n fillStyle: FillStyleSchema.nullable().optional(),\n components: z.array(ComponentSchema).optional()\n })\n .passthrough() // root μ μμ νλ (sky / exposure / hemi*/ dirLight* / camera* λ±)\n\n// ββ κ²μ¦ ν¬νΌ ββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\nexport interface ValidationResult {\n valid: boolean\n errors?: Array<{ path: string; message: string }>\n}\n\nfunction formatIssues(error: z.ZodError): Array<{ path: string; message: string }> {\n return error.issues.map(issue => ({\n path: issue.path.join('.'),\n message: issue.message\n }))\n}\n\n/** BoardModel μ 체 κ²μ¦. μμ / λ‘λ μ μ¬μ©. */\nexport function validateBoardModel(model: unknown): ValidationResult {\n const r = BoardModelSchema.safeParse(model)\n if (r.success) return { valid: true }\n return { valid: false, errors: formatIssues(r.error) }\n}\n\n/** modify patch κ²μ¦. AI κ° λ§λ patch κ° styling spec μ λ§λμ§. */\nexport function validateComponentPatch(patch: unknown): ValidationResult {\n const r = ComponentPatchSchema.safeParse(patch)\n if (r.success) return { valid: true }\n return { valid: false, errors: formatIssues(r.error) }\n}\n\n/** ν μ»΄ν¬λνΈ κ²μ¦. addComponent μ μ¬μ©. */\nexport function validateComponent(component: unknown): ValidationResult {\n const r = ComponentSchema.safeParse(component)\n if (r.success) return { valid: true }\n return { valid: false, errors: formatIssues(r.error) }\n}\n\n/** modifyBoard op μ patch κ²μ¦. 보λ root partial. */\nexport function validateBoardPatch(patch: unknown): ValidationResult {\n const r = BoardPatchSchema.safeParse(patch)\n if (r.success) return { valid: true }\n return { valid: false, errors: formatIssues(r.error) }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"board-model-schema.js","sourceRoot":"","sources":["../../../server/service/validation/board-model-schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * BoardModel zod schema β μμ / patch μ μ© boundary μμ λ°μ΄ν° λ¬΄κ²°μ± κ²μ¦.\n *\n * ν΅μ¬ μ μ±
:\n * - things-scene μ μ€μ drawer / setter ꡬνμ μ§μ€λ‘ λ΄ (μΈν°νμ΄μ€ declaration X)\n * - Component schema λ `.passthrough()` β μλ €μ§ νλ κ²μ¦ + λ―Έμ§ νλ ν΅κ³Ό\n * (μ¬μ©μ μ μ / λ°μ΄ν° λ°μΈλ© / μ»΄ν¬λνΈλ³ specific μμ± νμ©)\n * - κ·Έλ¬λ styling sub-objects (FillStyle / Shadow λ±) λ `.strict()` β unknown key\n * κ±°λΆ. stale μμ¬ νλ (μ: colorStops + colors 곡쑴) μλ λ°κ²¬.\n * - validation μ€ν¨ μ silent λλ½ X β caller κ° λͺ
μμ μλ¬ / λ‘κ·Έ\n *\n * μ μ© μ§μ :\n * 1. server `UpdateBoard` mutation μ§μ
β DB μμ μ§μ λ§μ§λ§ λ°©μ΄μ \n * 2. server `BoardAIChat` mutation μλ΅ μ§μ β AI κ° λ§λ patch μ μμ μ±\n * 3. (μ ν) client apply-patch μ μ© ν β λ©λͺ¨λ¦¬ μν 무결μ±\n */\nimport { z } from 'zod'\n\n// ββ Color ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\n/**\n * μμ β hex (#rgb / #rgba / #rrggbb / #rrggbbaa) / rgb / rgba / CSS named / 'transparent'.\n * μ κ·μμ λμ¨ β μ νν κ²μ¦μ normalizeColor κ°, μ¬κΈ°μ νμλ§.\n */\nconst ColorSchema = z.string().min(1).max(50)\n\n// ββ FillStyle (state.fillStyle) ββββββββββββββββββββββββββββββββββ\n//\n// μ€μ νμ (drawer/fill.ts κ²μ¦):\n// - solid: μμ string κ·Έλλ‘\n// - gradient: { type: 'gradient', gradientType, colorStops: [{position, color}], rotation?, opacity? }\n// - pattern: { type: 'pattern', image, ...μ΅μ
λ€ }\n// - none: undefined / null\n\nconst GradientStopSchema = z\n .object({\n position: z.number().min(0).max(1),\n color: ColorSchema\n })\n .strict()\n\nconst FillStyleGradientSchema = z\n .object({\n type: z.literal('gradient'),\n gradientType: z.enum(['linear', 'radial']).optional(),\n colorStops: z.array(GradientStopSchema).min(2),\n rotation: z.number().optional(),\n opacity: z.number().min(0).max(1).optional(),\n center: z\n .enum([\n 'center',\n 'left-top',\n 'left-bottom',\n 'right-top',\n 'right-bottom',\n 'left',\n 'right',\n 'top',\n 'bottom'\n ])\n .optional()\n })\n .strict()\n\nconst FillStylePatternSchema = z\n .object({\n type: z.literal('pattern'),\n image: z.union([z.string(), z.unknown()]),\n color: ColorSchema.optional(),\n fitPattern: z.boolean().optional(),\n noRepeat: z.boolean().optional(),\n align: z\n .enum([\n 'center',\n 'left-top',\n 'left-bottom',\n 'right-top',\n 'right-bottom',\n 'left',\n 'right',\n 'top',\n 'bottom'\n ])\n .optional(),\n offsetX: z.number().optional(),\n offsetY: z.number().optional(),\n width: z.number().optional(),\n height: z.number().optional(),\n opacity: z.number().min(0).max(1).optional(),\n guideOnly: z.boolean().optional()\n })\n .strict()\n\n/** 'none' type β fillStyle μ κ±° μλ νν (state.fillStyle = {type:'none'} λ νμ©). */\nconst FillStyleNoneSchema = z.object({ type: z.literal('none') }).strict()\n\nexport const FillStyleSchema = z.union([\n ColorSchema, // solid: '#xxx'\n FillStyleGradientSchema,\n FillStylePatternSchema,\n FillStyleNoneSchema,\n z.null()\n])\n\n// ββ Shadow (state.shadow) ββββββββββββββββββββββββββββββββββββββββ\n//\n// Canonical (CSS box-shadow / Canvas API νμ€): { color, offsetX, offsetY, blur }\n// Backwards-compat aliases (μ μ΄λ¦, drawer κ° fallback μΌλ‘ μ½μ): left / top / blurSize.\n// μμλ μ λ°μ΄ν° νΈνμ μν΄ λ μ΄λ¦ λ€ schema ν΅κ³Ό β μ μ½λλ canonical μ¬μ©.\n\nexport const ShadowSchema = z\n .object({\n color: ColorSchema.optional(),\n // canonical (CSS / Canvas νμ€)\n offsetX: z.number().optional(),\n offsetY: z.number().optional(),\n blur: z.number().min(0).optional(),\n // legacy aliases β μ things-scene λ°μ΄ν° νΈνμ©. μ μ½λλ μ canonical μ¬μ©.\n left: z.number().optional(),\n top: z.number().optional(),\n blurSize: z.number().min(0).optional()\n })\n .strict()\n\n// ββ Material3D (state.material3d) ββββββββββββββββββββββββββββββββ\n//\n// `things-scene/src/threed/material-3d.ts` μ Material3D μΈν°νμ΄μ€μ μΌμΉ.\n\nexport const Material3DSchema = z\n .object({\n preset: z\n .enum(['default', 'metal', 'glass', 'plastic', 'wood', 'ceramic', 'rubber', 'custom'])\n .optional(),\n metalness: z.number().min(0).max(1).optional(),\n roughness: z.number().min(0).max(1).optional(),\n emissive: ColorSchema.optional(),\n emissiveIntensity: z.number().min(0).max(5).optional(),\n opacity: z.number().min(0).max(1).optional(),\n envMapIntensity: z.number().min(0).max(3).optional(),\n side: z.enum(['double', 'front', 'back']).optional(),\n castShadow: z.boolean().optional(),\n receiveShadow: z.boolean().optional()\n })\n .strict()\n\n// ββ DataMapping (state.mappings) βββββββββββββββββββββββββββββββββ\n//\n// λ°μ΄ν° λ°μΈλ© β `interfaces/data.ts` Mapping. rule / target / accessor / converter / param.\n\nexport const MappingSchema = z\n .object({\n rule: z.string().optional(),\n target: z.string(),\n property: z.string().optional(),\n accessor: z.string().optional(),\n source: z.unknown().optional(),\n converter: z.union([z.string(), z.unknown()]).optional(),\n param: z.unknown().optional()\n })\n .passthrough() // mapping μ μμ νλ (converter args λ±) νμ©\n\n// ββ Component (one component in board.components) ββββββββββββββββ\n//\n// ν΅μ¬ styling νλλ λͺ
μ κ²μ¦, λλ¨Έμ§λ passthrough β μ»΄ν¬λνΈλ³ specific μμ± μμ .\n\nconst LineDashSchema = z.enum([\n 'solid',\n 'round-dot',\n 'square-dot',\n 'dash',\n 'dash-dot',\n 'long-dash',\n 'long-dash-dot',\n 'long-dash-dot-dot'\n])\n\n/**\n * μ»΄ν¬λνΈκ° *μ΄λ€ ννλ * μ ν¨ν geometry λ₯Ό κ°μ‘λμ§ νμΈ.\n *\n * things-scene μ μ»΄ν¬λνΈ type λ³λ‘ geometry νλκ° λ€μν¨ (rect λ box,\n * line μ endpoints, polyline μ vertices/path λ±). type β νλ λ§€νμ strict\n * νκ² enumerate νλ©΄ μ κ· type λ±λ‘ μ schema λ λμ μ
λ°μ΄νΈ νμ β forward\n * compatibility μν΄.\n *\n * λμ \"μ΅μν μ΄λ€ geometry νμμ΄λΌλ μμ΄μΌ νλ€\" λ μ½ν 보μ₯ β λΉ μ»΄ν¬λνΈ\n * (`{type:'rect'}` λ§) λλ type μ μ λ§λ geometry κ΅¬μ± (`{type:'rect', cx:10, cy:20}`)\n * κ°μ λͺ
λ°±ν μ€λ₯λ§ μ°¨λ¨. μ€μ λ λλ§ μ ν©μ±μ things-scene μμ²΄κ° κ²μ¦.\n */\nfunction componentHasValidGeometry(component: any): boolean {\n if (!component || typeof component !== 'object') return false\n\n // Box geometry β left/top λ λ€ μμ΄μΌ (width/height λ optional)\n const hasBox = typeof component.left === 'number' && typeof component.top === 'number'\n\n // Circle/ellipse geometry β cx/cy λ λ€ μμ΄μΌ\n const hasCircle = typeof component.cx === 'number' && typeof component.cy === 'number'\n\n // Line endpoints\n const hasLineEndpoints =\n typeof component.x1 === 'number' &&\n typeof component.y1 === 'number' &&\n typeof component.x2 === 'number' &&\n typeof component.y2 === 'number'\n\n // Path / points / vertices κ³μ΄\n const hasPath = typeof component.path === 'string' || Array.isArray(component.path)\n const hasPoints = Array.isArray(component.points) && component.points.length > 0\n const hasVertices =\n (Array.isArray(component.vertices) && component.vertices.length > 0) ||\n (Array.isArray(component.verticles) && component.verticles.length > 0) // legacy μ€ν\n\n // line connector β startPoint / endPoint νν (anchor κΈ°λ° line)\n const hasConnector =\n component.from && typeof component.from === 'object' &&\n component.to && typeof component.to === 'object'\n\n return hasBox || hasCircle || hasLineEndpoints || hasPath || hasPoints || hasVertices || hasConnector\n}\n\n/** type μ΄ 'gauge' λλ 'gauge-*' λ©΄ value νλ νμ (μ ν: min/max). */\nfunction isGaugeType(type: string): boolean {\n return type === 'gauge' || type.startsWith('gauge-')\n}\n\n/** type μ΄ 'chart' λλ 'chart-*' λ©΄ data νλ νμ. */\nfunction isChartType(type: string): boolean {\n return type === 'chart' || type.startsWith('chart-')\n}\n\nconst ComponentBaseSchema = z\n .object({\n type: z.string().min(1),\n refid: z.number().int().optional(), // μ κ· μ»΄ν¬λνΈ μΆκ° μμ μ λ―Έν λΉ κ°λ₯\n // μμΉ / ν¬κΈ° β μ»΄ν¬λνΈ νμ
μ λ°λΌ λ€λ¦. λ³Έ schema λ optional λ‘ λκ³ \n // refinement κ° *μ΄λ€ ννλ * μλμ§λ§ κ²μ¬.\n left: z.number().optional(),\n top: z.number().optional(),\n width: z.number().optional(),\n height: z.number().optional(),\n cx: z.number().optional(),\n cy: z.number().optional(),\n rx: z.number().optional(),\n ry: z.number().optional(),\n radius: z.number().optional(),\n x1: z.number().optional(),\n y1: z.number().optional(),\n x2: z.number().optional(),\n y2: z.number().optional(),\n rotation: z.number().optional(),\n // styling\n fillStyle: FillStyleSchema.optional(),\n strokeStyle: ColorSchema.optional(), // top-level string\n lineWidth: z.number().min(0).optional(),\n lineDash: LineDashSchema.optional(),\n lineCap: z.enum(['butt', 'round', 'square']).optional(),\n lineJoin: z.enum(['miter', 'round', 'bevel']).optional(),\n shadow: ShadowSchema.optional(),\n material3d: Material3DSchema.optional(),\n // text / font β top-level\n text: z.string().optional(),\n fontFamily: z.string().optional(),\n fontSize: z.number().positive().optional(),\n fontWeight: z.union([z.string(), z.number()]).optional(),\n fontStyle: z.string().optional(),\n fontColor: ColorSchema.optional(),\n textAlign: z.enum(['left', 'center', 'right', 'start', 'end', 'justify']).optional(),\n textBaseline: z\n .enum(['top', 'middle', 'bottom', 'hanging', 'alphabetic', 'ideographic'])\n .optional(),\n lineHeight: z.number().positive().optional(),\n // visibility / opacity\n alpha: z.number().min(0).max(1).optional(),\n hidden: z.boolean().optional(),\n // misc β κ²μ¦ μ ν¨\n id: z.string().optional(),\n class: z.string().optional(),\n tag: z.string().optional(),\n // λ°μ΄ν° λ°μΈλ©\n mappings: z.array(MappingSchema).optional()\n })\n .passthrough() // μ»΄ν¬λνΈλ³ specific μμ± (vehicle wheels, gauge needle, points/path λ±) νμ©\n\n/**\n * Component schema β base μμ type-aware refinement λ κ°μ§:\n *\n * 1. λͺ¨λ μ»΄ν¬λνΈλ *μ΄λ€ ννλ * μ ν¨ν geometry κ° μμ΄μΌ\n * (left+top / cx+cy / x1y1x2y2 / path / points / vertices / from+to)\n * 2. gauge-* type μ value νμ, chart-* type μ data νμ (soft check β\n * μΌλΆ prefab μ΄ λ―Έλ¦¬ μ±μμ£Όλ μΌμ΄μ€λ μμ΄ strict κ±°λΆλ³΄λ€ 미리 μ‘κΈ° λͺ©μ )\n *\n * μ΄ refinement λ€μ΄ LLM μ μλͺ»λ geometry (rect μ cx/cyλ§, line μ left/topλ§)\n * λ₯Ό μμ μ§μ μ°¨λ¨.\n */\nexport const ComponentSchema = ComponentBaseSchema.superRefine((component, ctx) => {\n if (!componentHasValidGeometry(component)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n `Component '${component.type}' has no valid geometry β provide left+top (box), cx+cy (circle/ellipse), x1+y1+x2+y2 (line), path / points / vertices, or from+to (connector).`\n })\n }\n\n if (isGaugeType(component.type) && component.value === undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['value'],\n message: `Component '${component.type}' requires 'value' (current sensor reading or display number).`\n })\n }\n\n if (isChartType(component.type) && component.data === undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['data'],\n message: `Component '${component.type}' requires 'data' (chart datapoints array or object).`\n })\n }\n})\n\n// ββ BoardModel (top-level) βββββββββββββββββββββββββββββββββββββββ\n\n/**\n * BoardModel β things-scene μ model-layer (보λ root).\n *\n * μΈμλλ root μμ± (model-layer μ NATURE.properties + μ€μ μ½λμμ state.* λ‘\n * μ°Έμ‘°λλ ν€):\n * β’ Layout: width, height, fitMode, translate, scale\n * β’ 2D λ°°κ²½: fillStyle\n * β’ 3D Sky: sky, skyColor\n * β’ 3D Tone: exposure\n * β’ 3D Hemisphere: hemiSkyColor, hemiGroundColor, hemiIntensity\n * β’ 3D Directional light: dirLightEnabled, dirLightColor, dirLightIntensity,\n * dirLightFollowCamera, dirLightAzimuth, dirLightElevation\n * β’ 3D Shadow: dirShadowEnabled, dirShadowMapSize, dirShadowBias\n * β’ 3D Camera: cameraX, cameraY, cameraZ, cameraAutoPlay, autoRotate, initialCameraView\n * β’ μλ³: id, refid, type\n *\n * β `name` μ things-scene model-layer κ° μΈμ μ ν¨ β Board *μν°ν°* μ 컬λΌμ΄μ§\n * scene MODEL μ νλκ° μλ. AI κ° modifyScene λ‘ name μ 보λ΄λ μ£½μ νλ. κ²μ¦\n * μμλ μ κ±° / 무μ μ μ±
.\n *\n * `passthrough` μΈ μ΄μ β 3D κ΄μ/μΉ΄λ©λΌ/sky λ± ν€κ° λ무 λ§μ strict λ‘λ νκ· μν\n * νΌ. λμ ν¨ν€μ§ μΈλΆ (operato λ±) κ° μμ root ν€ μΆκ°νλ κ±Έ λ§μ§ μμ.\n */\nexport const BoardModelSchema = z\n .object({\n width: z.number().positive(),\n height: z.number().positive(),\n fillStyle: FillStyleSchema.optional(), // 보λ λ°°κ²½\n components: z.array(ComponentSchema).optional()\n })\n .passthrough() // 보λ λ 벨 μμ νλ (3D atmosphere / sky / camera λ±)\n\n// ββ Patch op schemas β modify op μ patch κ° invalid μ΄λ©΄ κ±°λΆ βββ\n\n/**\n * modify op μ patch β μ»΄ν¬λνΈ partial. λͺ¨λ νλ optional. styling sub-object\n * λ§ strict νκ² κ²μ¦ν΄ stale key μμ‘΄ μ°¨λ¨.\n */\nexport const ComponentPatchSchema = z\n .object({\n fillStyle: FillStyleSchema.nullable().optional(),\n strokeStyle: ColorSchema.nullable().optional(),\n lineWidth: z.number().min(0).optional(),\n lineDash: LineDashSchema.optional(),\n lineCap: z.enum(['butt', 'round', 'square']).optional(),\n lineJoin: z.enum(['miter', 'round', 'bevel']).optional(),\n shadow: ShadowSchema.nullable().optional(),\n material3d: Material3DSchema.nullable().optional(),\n text: z.string().optional(),\n fontFamily: z.string().optional(),\n fontSize: z.number().positive().optional(),\n fontWeight: z.union([z.string(), z.number()]).optional(),\n fontStyle: z.string().optional(),\n fontColor: ColorSchema.optional(),\n textAlign: z.enum(['left', 'center', 'right', 'start', 'end', 'justify']).optional(),\n textBaseline: z\n .enum(['top', 'middle', 'bottom', 'hanging', 'alphabetic', 'ideographic'])\n .optional(),\n lineHeight: z.number().positive().optional(),\n alpha: z.number().min(0).max(1).optional(),\n hidden: z.boolean().optional()\n })\n .passthrough() // μμΉ / ν¬κΈ° / μ»΄ν¬λνΈ specific ν΅κ³Ό\n\n/**\n * modifyScene op μ patch β 보λ root partial.\n *\n * λͺ¨λ root νλ optional (BoardModelSchema μ λ¬λ¦¬ width/height λ optional).\n * passthrough λ‘ μλ €μ§μ§ μμ root ν€ (3D atmosphere, sky, camera λ±) ν΅κ³Ό.\n * λ€λ§ *μλ €μ§ nested object* (fillStyle λ±) λ strict schema μ¬μ¬μ© β κ·Έ μμ\n * unknown key κ° λ€μ΄μ€λ©΄ κ±°λΆ (μ: fillStyle μ gradientStops κ°μ stale μ΄λ¦).\n *\n * AI κ° setFill λ±μμ νμ΅ν vocabulary λ₯Ό modifyScene λ‘ echo μν¬ λ stale\n * key κ° fillStyle / shadow κ°μ sub-object μμ λΌλ©΄ λ³Έ schema κ° catch.\n */\nexport const BoardPatchSchema = z\n .object({\n width: z.number().positive().optional(),\n height: z.number().positive().optional(),\n fillStyle: FillStyleSchema.nullable().optional(),\n components: z.array(ComponentSchema).optional()\n })\n .passthrough() // root μ μμ νλ (sky / exposure / hemi*/ dirLight* / camera* λ±)\n\n// ββ κ²μ¦ ν¬νΌ ββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\nexport interface ValidationResult {\n valid: boolean\n errors?: Array<{ path: string; message: string }>\n}\n\nfunction formatIssues(error: z.ZodError): Array<{ path: string; message: string }> {\n return error.issues.map(issue => ({\n path: issue.path.join('.'),\n message: issue.message\n }))\n}\n\n/** BoardModel μ 체 κ²μ¦. μμ / λ‘λ μ μ¬μ©. */\nexport function validateBoardModel(model: unknown): ValidationResult {\n const r = BoardModelSchema.safeParse(model)\n if (r.success) return { valid: true }\n return { valid: false, errors: formatIssues(r.error) }\n}\n\n/** modify patch κ²μ¦. AI κ° λ§λ patch κ° styling spec μ λ§λμ§. */\nexport function validateComponentPatch(patch: unknown): ValidationResult {\n const r = ComponentPatchSchema.safeParse(patch)\n if (r.success) return { valid: true }\n return { valid: false, errors: formatIssues(r.error) }\n}\n\n/** ν μ»΄ν¬λνΈ κ²μ¦. addComponent μ μ¬μ©. */\nexport function validateComponent(component: unknown): ValidationResult {\n const r = ComponentSchema.safeParse(component)\n if (r.success) return { valid: true }\n return { valid: false, errors: formatIssues(r.error) }\n}\n\n/** modifyScene op μ patch κ²μ¦. 보λ root partial. */\nexport function validateBoardPatch(patch: unknown): ValidationResult {\n const r = BoardPatchSchema.safeParse(patch)\n if (r.success) return { valid: true }\n return { valid: false, errors: formatIssues(r.error) }\n}\n"]}
|
|
@@ -120,7 +120,7 @@ function validateWriteToolCall(tc, components = []) {
|
|
|
120
120
|
}
|
|
121
121
|
return { valid: true };
|
|
122
122
|
}
|
|
123
|
-
case '
|
|
123
|
+
case 'modifyScene': {
|
|
124
124
|
// 보λ root partial κ²μ¦ β fillStyle/shadow κ°μ nested μ strict schema κ°
|
|
125
125
|
// unknown key (e.g. fillStyle.gradientStops κ°μ stale μ΄λ¦) λ₯Ό κ±°λΆ.
|
|
126
126
|
// μ΄κ² λ§μ§λ§ λ°©μ΄μ β λ€λ₯Έ styling tool μμ νμ΅λ vocabulary κ° leak λλ©΄ catch.
|
|
@@ -132,7 +132,7 @@ function validateWriteToolCall(tc, components = []) {
|
|
|
132
132
|
return {
|
|
133
133
|
valid: false,
|
|
134
134
|
errors: formatValidationErrors(v),
|
|
135
|
-
suggestion:
|
|
135
|
+
suggestion: modifySceneSuggestion()
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
138
|
return { valid: true };
|
|
@@ -147,7 +147,7 @@ function validateWriteToolCall(tc, components = []) {
|
|
|
147
147
|
return {
|
|
148
148
|
valid: false,
|
|
149
149
|
errors: formatValidationErrors(v),
|
|
150
|
-
suggestion:
|
|
150
|
+
suggestion: modifySceneSuggestion()
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
153
|
return { valid: true };
|
|
@@ -157,8 +157,8 @@ function validateWriteToolCall(tc, components = []) {
|
|
|
157
157
|
return { valid: true };
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
-
function
|
|
161
|
-
return ('
|
|
160
|
+
function modifySceneSuggestion() {
|
|
161
|
+
return ('modifyScene μ patch λ things-scene μ model-layer κ° μΈμνλ root key λ§ μ¬μ©. ' +
|
|
162
162
|
'fillStyle / strokeStyle / shadow κ°μ nested object μ μμͺ½ νλλ canonical μ΄λ¦ (colorStops λ±) μ νν μ¬μ©. ' +
|
|
163
163
|
'rect λ± μμ μ»΄ν¬λνΈ λ³κ²½μ modifyComponentByRefid λ‘ λΆλ¦¬.');
|
|
164
164
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-validation.js","sourceRoot":"","sources":["../../../server/service/validation/tool-validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Write tool μ μ¬μ κ²μ¦ β agentic loop μ retry λ©μ»€λμ¦.\n *\n * νλ¦:\n * 1. LLM μ΄ write tool νΈμΆ\n * 2. λ³Έ ν¨μκ° args κ²μ¦ (styling tool μ build* ν¨μ λλ schema μ§μ )\n * 3. μ€ν¨ μ errors λ°ν β caller κ° tool_result μ error λ©μμ§ λ΄μ LLM νν
\n * 4. LLM λ€μ turn μμ μ μ ν μ¬νΈμΆ (μκΈ° ν볡)\n *\n * μ΄κ² silent λ°μ΄ν° μμμ λ§λ λ§μ§λ§ λ₯λ λ°©μ΄μ . κ²μ¦ ν΅κ³Όν args λ§ λμ \n * β patch λ‘ λ³νλλ―λ‘ κΉ¨μ§ λ°μ΄ν°κ° μμκΉμ§ λͺ» κ°.\n */\nimport type { AIToolCall } from '@things-factory/ai-client-base'\nimport {\n validateComponentPatch,\n validateComponent,\n validateBoardPatch,\n type ValidationResult\n} from './board-model-schema'\nimport { buildSetFillOps } from '../styling/fill-tools'\nimport { buildSetStrokeOps } from '../styling/stroke-tools'\nimport { buildSetTextOps, buildSetFontOps } from '../styling/text-tools'\nimport {\n buildSetShadowOps,\n buildSetOpacityOps,\n buildSetVisibleOps\n} from '../styling/effect-tools'\nimport {\n buildSetMaterialOps,\n buildSetShadowPropertiesOps\n} from '../styling/material-tools'\nimport { buildClearStyleOps } from '../styling/clear-tools'\nimport { buildCopyStyleOps } from '../styling/copy-tools'\n\nexport interface ToolValidationResult {\n /** κ²μ¦ ν΅κ³Ό β λμ μ§ν κ°λ₯ */\n valid: boolean\n /** μ€ν¨ μ LLM νν
λ³΄μΌ μλ¬ λ©μμ§ (μκΈ° ν볡 μ 보 ν¬ν¨) */\n errors?: string[]\n /** LLM νν
μ μ κ°μ΄λ β κ°λ₯ν κ²½μ° μ΄λ€ νμμ΄ λ§λμ§ */\n suggestion?: string\n}\n\n/**\n * write tool μ args μ¬μ κ²μ¦.\n *\n * μ μ±
:\n * - styling tool: ν΄λΉ build* ν¨μκ° errors λ°ν β κ·Έλλ‘ LLM νν
\n * - modifyComponentByRefid: ComponentPatchSchema λ‘ κ²μ¦ (raw fallback μμ)\n * - addComponent: ComponentSchema λ‘ κ²μ¦\n * - κ·Έ μΈ: κΈ°μ‘΄ dispatcher μ μ체 κ²μ¦μ μμ (μ¬μλ 보μ₯ X)\n */\nexport function validateWriteToolCall(\n tc: AIToolCall,\n components: ReadonlyArray<any> = []\n): ToolValidationResult {\n const args = tc.arguments ?? {}\n\n // Styling tool λ€ β κ° build ν¨μκ° detailed errors λ°ν\n switch (tc.name) {\n case 'setFill': {\n const r = buildSetFillOps(args as any)\n if (r.errors.length > 0)\n return {\n valid: false,\n errors: r.errors,\n suggestion: setFillSuggestion()\n }\n return { valid: true }\n }\n case 'setStroke': {\n const r = buildSetStrokeOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setText': {\n const r = buildSetTextOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setFont': {\n const r = buildSetFontOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setShadow': {\n const r = buildSetShadowOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setOpacity': {\n const r = buildSetOpacityOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setVisible': {\n const r = buildSetVisibleOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setMaterial': {\n const r = buildSetMaterialOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setShadowProperties': {\n const r = buildSetShadowPropertiesOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'clearStyle': {\n const r = buildClearStyleOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'copyStyle': {\n const r = buildCopyStyleOps(args as any, components)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n\n // raw fallback β schema κ²μ¦\n case 'modifyComponentByRefid': {\n if (typeof args.refid !== 'number') {\n return { valid: false, errors: ['refid (number) is required'] }\n }\n if (!args.patch || typeof args.patch !== 'object') {\n return { valid: false, errors: ['patch (object) is required'] }\n }\n const v = validateComponentPatch(args.patch)\n if (!v.valid) {\n return {\n valid: false,\n errors: formatValidationErrors(v),\n suggestion: modifyPatchSuggestion()\n }\n }\n return { valid: true }\n }\n case 'addComponent': {\n const v = validateComponent(args)\n if (!v.valid) {\n return {\n valid: false,\n errors: formatValidationErrors(v)\n }\n }\n return { valid: true }\n }\n case 'modifyBoard': {\n // 보λ root partial κ²μ¦ β fillStyle/shadow κ°μ nested μ strict schema κ°\n // unknown key (e.g. fillStyle.gradientStops κ°μ stale μ΄λ¦) λ₯Ό κ±°λΆ.\n // μ΄κ² λ§μ§λ§ λ°©μ΄μ β λ€λ₯Έ styling tool μμ νμ΅λ vocabulary κ° leak λλ©΄ catch.\n if (!args.patch || typeof args.patch !== 'object' || Array.isArray(args.patch)) {\n return { valid: false, errors: ['patch (object) is required'] }\n }\n const v = validateBoardPatch(args.patch)\n if (!v.valid) {\n return {\n valid: false,\n errors: formatValidationErrors(v),\n suggestion: modifyBoardSuggestion()\n }\n }\n return { valid: true }\n }\n case 'replaceBoard': {\n // 보λ ν΅μ§Έ κ΅μ²΄ β μμ μ§μ κ°μ₯ κ°λ ₯ν κ²μ¦ νμ. components κΉμ§ ν λ²μ\n // κ²μ¬. μμ μ»΄ν¬λνΈμ fillStyle.gradientStops κ°μ stale ν€λ μ¦μ catch.\n // (BoardPatchSchema λ component λ array λ‘ ν΅κ³Όμν€λ ComponentSchema κ°\n // strict styling sub-objects λ‘ stale μ°¨λ¨.)\n const v = validateBoardPatch(args)\n if (!v.valid) {\n return {\n valid: false,\n errors: formatValidationErrors(v),\n suggestion: modifyBoardSuggestion()\n }\n }\n return { valid: true }\n }\n\n // κ·Έ μΈ β κΈ°μ‘΄ dispatcher κ²μ¦μ μμ\n default:\n return { valid: true }\n }\n}\n\nfunction modifyBoardSuggestion(): string {\n return (\n 'modifyBoard μ patch λ things-scene μ model-layer κ° μΈμνλ root key λ§ μ¬μ©. ' +\n 'fillStyle / strokeStyle / shadow κ°μ nested object μ μμͺ½ νλλ canonical μ΄λ¦ (colorStops λ±) μ νν μ¬μ©. ' +\n 'rect λ± μμ μ»΄ν¬λνΈ λ³κ²½μ modifyComponentByRefid λ‘ λΆλ¦¬.'\n )\n}\n\nfunction formatValidationErrors(v: ValidationResult): string[] {\n if (v.valid || !v.errors) return []\n return v.errors.map(e => `${e.path || '<root>'}: ${e.message}`)\n}\n\n/**\n * setFill μ μ κ°μ΄λ β μμ£Ό μ€μνλ ν¨ν΄ + μ¬λ°λ₯Έ μμ.\n */\nfunction setFillSuggestion(): string {\n return [\n 'Valid setFill patterns:',\n \" - Solid: { refids:[35], mode:'solid', color:'#ff0000' }\",\n \" - Gradient: { refids:[35], mode:'gradient', gradientType:'linear', \" +\n \"colorStops:[{position:0,color:'#ff0000'},{position:1,color:'#0000ff'}], rotation:90 }\",\n \" - Pattern: { refids:[35], mode:'pattern', image:'url' }\",\n \" - Partial color update: { refids:[35], color:'green' } // mode λ―Έμ§μ \",\n 'Notes:',\n ' - rotation μ degrees λ‘ μ
λ ₯ (μλ²κ° λΌλμμΌλ‘ λ³νν΄ fillStyle.rotation μ μ μ₯)',\n ' - colorStops λ { position: 0..1, color: hex/rgb/named } κ°μ²΄ λ°°μ΄',\n ' - μ μ΄λ¦ (colors / stops / gradientStops) μ¬μ© κΈμ§ β engine canonical μ colorStops'\n ].join('\\n')\n}\n\nfunction modifyPatchSuggestion(): string {\n return [\n 'modifyComponentByRefid is the raw fallback β prefer specific styling tools (setFill/setStroke/setText/setFont/setShadow/setMaterial/setOpacity/setVisible) for any styling change.',\n 'If you must use raw modify:',\n ' - fillStyle string (solid) or {type:\"gradient\",gradientType,colorStops:[{position,color}]} or {type:\"pattern\",image,...}',\n ' - shadow {color, offsetX, offsetY, blur} (CSS box-shadow / Canvas νμ€ μ΄λ¦)',\n ' - lineDash STRING preset only (NOT number array)'\n ].join('\\n')\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tool-validation.js","sourceRoot":"","sources":["../../../server/service/validation/tool-validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Write tool μ μ¬μ κ²μ¦ β agentic loop μ retry λ©μ»€λμ¦.\n *\n * νλ¦:\n * 1. LLM μ΄ write tool νΈμΆ\n * 2. λ³Έ ν¨μκ° args κ²μ¦ (styling tool μ build* ν¨μ λλ schema μ§μ )\n * 3. μ€ν¨ μ errors λ°ν β caller κ° tool_result μ error λ©μμ§ λ΄μ LLM νν
\n * 4. LLM λ€μ turn μμ μ μ ν μ¬νΈμΆ (μκΈ° ν볡)\n *\n * μ΄κ² silent λ°μ΄ν° μμμ λ§λ λ§μ§λ§ λ₯λ λ°©μ΄μ . κ²μ¦ ν΅κ³Όν args λ§ λμ \n * β patch λ‘ λ³νλλ―λ‘ κΉ¨μ§ λ°μ΄ν°κ° μμκΉμ§ λͺ» κ°.\n */\nimport type { AIToolCall } from '@things-factory/ai-client-base'\nimport {\n validateComponentPatch,\n validateComponent,\n validateBoardPatch,\n type ValidationResult\n} from './board-model-schema'\nimport { buildSetFillOps } from '../styling/fill-tools'\nimport { buildSetStrokeOps } from '../styling/stroke-tools'\nimport { buildSetTextOps, buildSetFontOps } from '../styling/text-tools'\nimport {\n buildSetShadowOps,\n buildSetOpacityOps,\n buildSetVisibleOps\n} from '../styling/effect-tools'\nimport {\n buildSetMaterialOps,\n buildSetShadowPropertiesOps\n} from '../styling/material-tools'\nimport { buildClearStyleOps } from '../styling/clear-tools'\nimport { buildCopyStyleOps } from '../styling/copy-tools'\n\nexport interface ToolValidationResult {\n /** κ²μ¦ ν΅κ³Ό β λμ μ§ν κ°λ₯ */\n valid: boolean\n /** μ€ν¨ μ LLM νν
λ³΄μΌ μλ¬ λ©μμ§ (μκΈ° ν볡 μ 보 ν¬ν¨) */\n errors?: string[]\n /** LLM νν
μ μ κ°μ΄λ β κ°λ₯ν κ²½μ° μ΄λ€ νμμ΄ λ§λμ§ */\n suggestion?: string\n}\n\n/**\n * write tool μ args μ¬μ κ²μ¦.\n *\n * μ μ±
:\n * - styling tool: ν΄λΉ build* ν¨μκ° errors λ°ν β κ·Έλλ‘ LLM νν
\n * - modifyComponentByRefid: ComponentPatchSchema λ‘ κ²μ¦ (raw fallback μμ)\n * - addComponent: ComponentSchema λ‘ κ²μ¦\n * - κ·Έ μΈ: κΈ°μ‘΄ dispatcher μ μ체 κ²μ¦μ μμ (μ¬μλ 보μ₯ X)\n */\nexport function validateWriteToolCall(\n tc: AIToolCall,\n components: ReadonlyArray<any> = []\n): ToolValidationResult {\n const args = tc.arguments ?? {}\n\n // Styling tool λ€ β κ° build ν¨μκ° detailed errors λ°ν\n switch (tc.name) {\n case 'setFill': {\n const r = buildSetFillOps(args as any)\n if (r.errors.length > 0)\n return {\n valid: false,\n errors: r.errors,\n suggestion: setFillSuggestion()\n }\n return { valid: true }\n }\n case 'setStroke': {\n const r = buildSetStrokeOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setText': {\n const r = buildSetTextOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setFont': {\n const r = buildSetFontOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setShadow': {\n const r = buildSetShadowOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setOpacity': {\n const r = buildSetOpacityOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setVisible': {\n const r = buildSetVisibleOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setMaterial': {\n const r = buildSetMaterialOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'setShadowProperties': {\n const r = buildSetShadowPropertiesOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'clearStyle': {\n const r = buildClearStyleOps(args as any)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n case 'copyStyle': {\n const r = buildCopyStyleOps(args as any, components)\n if (r.errors.length > 0) return { valid: false, errors: r.errors }\n return { valid: true }\n }\n\n // raw fallback β schema κ²μ¦\n case 'modifyComponentByRefid': {\n if (typeof args.refid !== 'number') {\n return { valid: false, errors: ['refid (number) is required'] }\n }\n if (!args.patch || typeof args.patch !== 'object') {\n return { valid: false, errors: ['patch (object) is required'] }\n }\n const v = validateComponentPatch(args.patch)\n if (!v.valid) {\n return {\n valid: false,\n errors: formatValidationErrors(v),\n suggestion: modifyPatchSuggestion()\n }\n }\n return { valid: true }\n }\n case 'addComponent': {\n const v = validateComponent(args)\n if (!v.valid) {\n return {\n valid: false,\n errors: formatValidationErrors(v)\n }\n }\n return { valid: true }\n }\n case 'modifyScene': {\n // 보λ root partial κ²μ¦ β fillStyle/shadow κ°μ nested μ strict schema κ°\n // unknown key (e.g. fillStyle.gradientStops κ°μ stale μ΄λ¦) λ₯Ό κ±°λΆ.\n // μ΄κ² λ§μ§λ§ λ°©μ΄μ β λ€λ₯Έ styling tool μμ νμ΅λ vocabulary κ° leak λλ©΄ catch.\n if (!args.patch || typeof args.patch !== 'object' || Array.isArray(args.patch)) {\n return { valid: false, errors: ['patch (object) is required'] }\n }\n const v = validateBoardPatch(args.patch)\n if (!v.valid) {\n return {\n valid: false,\n errors: formatValidationErrors(v),\n suggestion: modifySceneSuggestion()\n }\n }\n return { valid: true }\n }\n case 'replaceBoard': {\n // 보λ ν΅μ§Έ κ΅μ²΄ β μμ μ§μ κ°μ₯ κ°λ ₯ν κ²μ¦ νμ. components κΉμ§ ν λ²μ\n // κ²μ¬. μμ μ»΄ν¬λνΈμ fillStyle.gradientStops κ°μ stale ν€λ μ¦μ catch.\n // (BoardPatchSchema λ component λ array λ‘ ν΅κ³Όμν€λ ComponentSchema κ°\n // strict styling sub-objects λ‘ stale μ°¨λ¨.)\n const v = validateBoardPatch(args)\n if (!v.valid) {\n return {\n valid: false,\n errors: formatValidationErrors(v),\n suggestion: modifySceneSuggestion()\n }\n }\n return { valid: true }\n }\n\n // κ·Έ μΈ β κΈ°μ‘΄ dispatcher κ²μ¦μ μμ\n default:\n return { valid: true }\n }\n}\n\nfunction modifySceneSuggestion(): string {\n return (\n 'modifyScene μ patch λ things-scene μ model-layer κ° μΈμνλ root key λ§ μ¬μ©. ' +\n 'fillStyle / strokeStyle / shadow κ°μ nested object μ μμͺ½ νλλ canonical μ΄λ¦ (colorStops λ±) μ νν μ¬μ©. ' +\n 'rect λ± μμ μ»΄ν¬λνΈ λ³κ²½μ modifyComponentByRefid λ‘ λΆλ¦¬.'\n )\n}\n\nfunction formatValidationErrors(v: ValidationResult): string[] {\n if (v.valid || !v.errors) return []\n return v.errors.map(e => `${e.path || '<root>'}: ${e.message}`)\n}\n\n/**\n * setFill μ μ κ°μ΄λ β μμ£Ό μ€μνλ ν¨ν΄ + μ¬λ°λ₯Έ μμ.\n */\nfunction setFillSuggestion(): string {\n return [\n 'Valid setFill patterns:',\n \" - Solid: { refids:[35], mode:'solid', color:'#ff0000' }\",\n \" - Gradient: { refids:[35], mode:'gradient', gradientType:'linear', \" +\n \"colorStops:[{position:0,color:'#ff0000'},{position:1,color:'#0000ff'}], rotation:90 }\",\n \" - Pattern: { refids:[35], mode:'pattern', image:'url' }\",\n \" - Partial color update: { refids:[35], color:'green' } // mode λ―Έμ§μ \",\n 'Notes:',\n ' - rotation μ degrees λ‘ μ
λ ₯ (μλ²κ° λΌλμμΌλ‘ λ³νν΄ fillStyle.rotation μ μ μ₯)',\n ' - colorStops λ { position: 0..1, color: hex/rgb/named } κ°μ²΄ λ°°μ΄',\n ' - μ μ΄λ¦ (colors / stops / gradientStops) μ¬μ© κΈμ§ β engine canonical μ colorStops'\n ].join('\\n')\n}\n\nfunction modifyPatchSuggestion(): string {\n return [\n 'modifyComponentByRefid is the raw fallback β prefer specific styling tools (setFill/setStroke/setText/setFont/setShadow/setMaterial/setOpacity/setVisible) for any styling change.',\n 'If you must use raw modify:',\n ' - fillStyle string (solid) or {type:\"gradient\",gradientType,colorStops:[{position,color}]} or {type:\"pattern\",image,...}',\n ' - shadow {color, offsetX, offsetY, blur} (CSS box-shadow / Canvas νμ€ μ΄λ¦)',\n ' - lineDash STRING preset only (NOT number array)'\n ].join('\\n')\n}\n"]}
|