@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.
Files changed (107) hide show
  1. package/PLAN-styling-tools.md +1 -1
  2. package/dist-client/server/service/assistant.d.ts +5 -4
  3. package/dist-client/server/service/assistant.js +35 -35
  4. package/dist-client/server/service/assistant.js.map +1 -1
  5. package/dist-client/server/service/styling/clear-tools.d.ts +2 -2
  6. package/dist-client/server/service/styling/clear-tools.js.map +1 -1
  7. package/dist-client/server/service/styling/copy-tools.d.ts +3 -3
  8. package/dist-client/server/service/styling/copy-tools.js +1 -1
  9. package/dist-client/server/service/styling/copy-tools.js.map +1 -1
  10. package/dist-client/server/service/styling/effect-tools.d.ts +2 -2
  11. package/dist-client/server/service/styling/effect-tools.js.map +1 -1
  12. package/dist-client/server/service/styling/fill-tools.d.ts +3 -3
  13. package/dist-client/server/service/styling/fill-tools.js +1 -1
  14. package/dist-client/server/service/styling/fill-tools.js.map +1 -1
  15. package/dist-client/server/service/styling/material-tools.d.ts +2 -2
  16. package/dist-client/server/service/styling/material-tools.js.map +1 -1
  17. package/dist-client/server/service/styling/registry.d.ts +6 -6
  18. package/dist-client/server/service/styling/registry.js +2 -2
  19. package/dist-client/server/service/styling/registry.js.map +1 -1
  20. package/dist-client/server/service/styling/stroke-tools.d.ts +2 -2
  21. package/dist-client/server/service/styling/stroke-tools.js.map +1 -1
  22. package/dist-client/server/service/styling/text-tools.d.ts +2 -2
  23. package/dist-client/server/service/styling/text-tools.js.map +1 -1
  24. package/dist-client/server/service/types.d.ts +6 -148
  25. package/dist-client/server/service/types.js.map +1 -1
  26. package/dist-client/server/service/validation/board-model-schema.d.ts +262 -262
  27. package/dist-client/server/service/validation/board-model-schema.js +4 -4
  28. package/dist-client/server/service/validation/board-model-schema.js.map +1 -1
  29. package/dist-client/server/service/validation/tool-validation.js +5 -5
  30. package/dist-client/server/service/validation/tool-validation.js.map +1 -1
  31. package/dist-client/tsconfig.tsbuildinfo +1 -1
  32. package/dist-server/index.d.ts +2 -2
  33. package/dist-server/index.js +2 -2
  34. package/dist-server/index.js.map +1 -1
  35. package/dist-server/service/assistant.d.ts +5 -4
  36. package/dist-server/service/assistant.js +37 -37
  37. package/dist-server/service/assistant.js.map +1 -1
  38. package/dist-server/service/board-ai-resolver.js +2 -2
  39. package/dist-server/service/board-ai-resolver.js.map +1 -1
  40. package/dist-server/service/index.d.ts +0 -1
  41. package/dist-server/service/index.js +0 -1
  42. package/dist-server/service/index.js.map +1 -1
  43. package/dist-server/service/patch-entry/board-patch-subscription.js +1 -1
  44. package/dist-server/service/patch-entry/board-patch-subscription.js.map +1 -1
  45. package/dist-server/service/patch-entry/patch-entry.d.ts +1 -1
  46. package/dist-server/service/patch-entry/patch-entry.js +1 -1
  47. package/dist-server/service/patch-entry/patch-entry.js.map +1 -1
  48. package/dist-server/service/styling/clear-tools.d.ts +2 -2
  49. package/dist-server/service/styling/clear-tools.js.map +1 -1
  50. package/dist-server/service/styling/copy-tools.d.ts +3 -3
  51. package/dist-server/service/styling/copy-tools.js +1 -1
  52. package/dist-server/service/styling/copy-tools.js.map +1 -1
  53. package/dist-server/service/styling/effect-tools.d.ts +2 -2
  54. package/dist-server/service/styling/effect-tools.js.map +1 -1
  55. package/dist-server/service/styling/fill-tools.d.ts +3 -3
  56. package/dist-server/service/styling/fill-tools.js +1 -1
  57. package/dist-server/service/styling/fill-tools.js.map +1 -1
  58. package/dist-server/service/styling/material-tools.d.ts +2 -2
  59. package/dist-server/service/styling/material-tools.js.map +1 -1
  60. package/dist-server/service/styling/registry.d.ts +6 -6
  61. package/dist-server/service/styling/registry.js +2 -2
  62. package/dist-server/service/styling/registry.js.map +1 -1
  63. package/dist-server/service/styling/stroke-tools.d.ts +2 -2
  64. package/dist-server/service/styling/stroke-tools.js.map +1 -1
  65. package/dist-server/service/styling/text-tools.d.ts +2 -2
  66. package/dist-server/service/styling/text-tools.js.map +1 -1
  67. package/dist-server/service/types.d.ts +6 -148
  68. package/dist-server/service/types.js.map +1 -1
  69. package/dist-server/service/validation/board-model-schema.d.ts +262 -262
  70. package/dist-server/service/validation/board-model-schema.js +4 -4
  71. package/dist-server/service/validation/board-model-schema.js.map +1 -1
  72. package/dist-server/service/validation/tool-validation.js +5 -5
  73. package/dist-server/service/validation/tool-validation.js.map +1 -1
  74. package/dist-server/tsconfig.tsbuildinfo +1 -1
  75. package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +5 -0
  76. package/logs/connections-2026-09-17-16.log +0 -0
  77. package/package.json +8 -7
  78. package/server/index.ts +2 -2
  79. package/server/service/assistant-integration.test.ts +44 -44
  80. package/server/service/assistant-llm-smoke.test.ts +5 -5
  81. package/server/service/assistant.test.ts +86 -86
  82. package/server/service/assistant.ts +41 -43
  83. package/server/service/board-ai-resolver.ts +2 -2
  84. package/server/service/index.ts +0 -1
  85. package/server/service/patch-entry/board-patch-subscription.ts +1 -1
  86. package/server/service/patch-entry/patch-entry.ts +2 -2
  87. package/server/service/styling/clear-tools.ts +2 -2
  88. package/server/service/styling/copy-tools.ts +3 -3
  89. package/server/service/styling/effect-tools.ts +2 -2
  90. package/server/service/styling/fill-tools.test.ts +1 -1
  91. package/server/service/styling/fill-tools.ts +4 -4
  92. package/server/service/styling/material-tools.ts +2 -2
  93. package/server/service/styling/registry.ts +6 -6
  94. package/server/service/styling/stroke-tools.test.ts +1 -1
  95. package/server/service/styling/stroke-tools.ts +3 -3
  96. package/server/service/styling/text-tools.ts +2 -2
  97. package/server/service/tool-exposure.test.ts +7 -7
  98. package/server/service/types.ts +9 -110
  99. package/server/service/validation/board-model-schema.test.ts +3 -3
  100. package/server/service/validation/board-model-schema.ts +4 -4
  101. package/server/service/validation/tool-validation.ts +5 -5
  102. package/dist-server/service/apply-patch.d.ts +0 -47
  103. package/dist-server/service/apply-patch.js +0 -369
  104. package/dist-server/service/apply-patch.js.map +0 -1
  105. package/server/service/apply-patch-drift.test.ts +0 -831
  106. package/server/service/apply-patch.test.ts +0 -757
  107. package/server/service/apply-patch.ts +0 -411
@@ -2,13 +2,13 @@
2
2
  * assistant.ts 의 pure helper 회귀 방지.
3
3
  *
4
4
  * 핵심 보호:
5
- * - LLM tool call → BoardEditOp 매핑이 잘못된 인자에서도 안전
5
+ * - LLM tool call → SceneEditOp 매핑이 잘못된 인자에서도 안전
6
6
  * - JSON fallback 응답 정규화: 망가진 ops, 빠진 confidence, 잘못된 타입에서도 적절히 무시
7
7
  * - summarizeBoard: 토큰 절감 — 컴포넌트 수 제한, 필요 속성만 노출
8
8
  */
9
9
  import {
10
- toolCallToBoardEditOp,
11
- toolCallToBoardActionOp,
10
+ toolCallToSceneEditOp,
11
+ toolCallToSceneActionOp,
12
12
  toolResultToChatResponse,
13
13
  isReadTool,
14
14
  isWriteTool,
@@ -21,9 +21,9 @@ import {
21
21
  } from './assistant'
22
22
  import { isGroundedAnalysisContract } from '@things-factory/ai-client-base'
23
23
 
24
- describe('toolCallToBoardEditOp', () => {
24
+ describe('toolCallToSceneEditOp', () => {
25
25
  test('addComponent: 정상 인자', () => {
26
- const r = toolCallToBoardEditOp({
26
+ const r = toolCallToSceneEditOp({
27
27
  id: '1',
28
28
  name: 'addComponent',
29
29
  arguments: { id: 'a', type: 'rect', left: 0, top: 0 }
@@ -32,12 +32,12 @@ describe('toolCallToBoardEditOp', () => {
32
32
  })
33
33
 
34
34
  test('addComponent: type 누락 → null', () => {
35
- const r = toolCallToBoardEditOp({ id: '1', name: 'addComponent', arguments: { id: 'a' } } as any)
35
+ const r = toolCallToSceneEditOp({ id: '1', name: 'addComponent', arguments: { id: 'a' } } as any)
36
36
  expect(r).toBeNull()
37
37
  })
38
38
 
39
39
  test('removeComponentByRefid: 정상', () => {
40
- const r = toolCallToBoardEditOp({
40
+ const r = toolCallToSceneEditOp({
41
41
  id: '1',
42
42
  name: 'removeComponentByRefid',
43
43
  arguments: { refid: 35 }
@@ -46,7 +46,7 @@ describe('toolCallToBoardEditOp', () => {
46
46
  })
47
47
 
48
48
  test('removeComponentByRefid: refid 누락 → null', () => {
49
- const r = toolCallToBoardEditOp({
49
+ const r = toolCallToSceneEditOp({
50
50
  id: '1',
51
51
  name: 'removeComponentByRefid',
52
52
  arguments: {}
@@ -55,7 +55,7 @@ describe('toolCallToBoardEditOp', () => {
55
55
  })
56
56
 
57
57
  test('removeComponentByRefid: refid 가 number 아니면 null (id 로는 targeting 안 함)', () => {
58
- const r = toolCallToBoardEditOp({
58
+ const r = toolCallToSceneEditOp({
59
59
  id: '1',
60
60
  name: 'removeComponentByRefid',
61
61
  arguments: { refid: 'AGV-1' }
@@ -64,7 +64,7 @@ describe('toolCallToBoardEditOp', () => {
64
64
  })
65
65
 
66
66
  test('modifyComponentByRefid: 정상', () => {
67
- const r = toolCallToBoardEditOp({
67
+ const r = toolCallToSceneEditOp({
68
68
  id: '1',
69
69
  name: 'modifyComponentByRefid',
70
70
  arguments: { refid: 35, patch: { left: 100 } }
@@ -73,7 +73,7 @@ describe('toolCallToBoardEditOp', () => {
73
73
  })
74
74
 
75
75
  test('modifyComponentByRefid: patch 가 객체가 아니면 null', () => {
76
- const r = toolCallToBoardEditOp({
76
+ const r = toolCallToSceneEditOp({
77
77
  id: '1',
78
78
  name: 'modifyComponentByRefid',
79
79
  arguments: { refid: 35, patch: 'string' }
@@ -82,7 +82,7 @@ describe('toolCallToBoardEditOp', () => {
82
82
  })
83
83
 
84
84
  test('modifyComponentByRefid: refid 누락 → null', () => {
85
- const r = toolCallToBoardEditOp({
85
+ const r = toolCallToSceneEditOp({
86
86
  id: '1',
87
87
  name: 'modifyComponentByRefid',
88
88
  arguments: { patch: { left: 100 } }
@@ -92,52 +92,52 @@ describe('toolCallToBoardEditOp', () => {
92
92
 
93
93
  test('legacy 이름 (removeComponent / modifyComponent / getComponent) → null', () => {
94
94
  // 이름이 refid 기반으로 명시 변경됐다 — legacy 이름은 invalid 로 거부.
95
- expect(toolCallToBoardEditOp({ id: '1', name: 'removeComponent', arguments: { id: 'a' } } as any)).toBeNull()
95
+ expect(toolCallToSceneEditOp({ id: '1', name: 'removeComponent', arguments: { id: 'a' } } as any)).toBeNull()
96
96
  expect(
97
- toolCallToBoardEditOp({ id: '1', name: 'modifyComponent', arguments: { id: 'a', patch: {} } } as any)
97
+ toolCallToSceneEditOp({ id: '1', name: 'modifyComponent', arguments: { id: 'a', patch: {} } } as any)
98
98
  ).toBeNull()
99
99
  })
100
100
 
101
- test('modifyBoard: patch 객체 정상 — root 속성 변경', () => {
102
- const r = toolCallToBoardEditOp({
101
+ test('modifyScene: patch 객체 정상 — root 속성 변경', () => {
102
+ const r = toolCallToSceneEditOp({
103
103
  id: '1',
104
- name: 'modifyBoard',
104
+ name: 'modifyScene',
105
105
  arguments: { patch: { fillStyle: '#0a1929' } }
106
106
  } as any)
107
- expect(r).toEqual({ op: 'modifyBoard', patch: { fillStyle: '#0a1929' } })
107
+ expect(r).toEqual({ op: 'modifyScene', patch: { fillStyle: '#0a1929' } })
108
108
  })
109
109
 
110
- test('modifyBoard: patch 누락 → null', () => {
110
+ test('modifyScene: patch 누락 → null', () => {
111
111
  expect(
112
- toolCallToBoardEditOp({ id: '1', name: 'modifyBoard', arguments: {} } as any)
112
+ toolCallToSceneEditOp({ id: '1', name: 'modifyScene', arguments: {} } as any)
113
113
  ).toBeNull()
114
114
  })
115
115
 
116
- test('modifyBoard: patch 가 array 면 null (object 만 허용)', () => {
116
+ test('modifyScene: patch 가 array 면 null (object 만 허용)', () => {
117
117
  expect(
118
- toolCallToBoardEditOp({
118
+ toolCallToSceneEditOp({
119
119
  id: '1',
120
- name: 'modifyBoard',
120
+ name: 'modifyScene',
121
121
  arguments: { patch: [1, 2] }
122
122
  } as any)
123
123
  ).toBeNull()
124
124
  })
125
125
 
126
- test('modifyBoard: 다중 root 속성 변경', () => {
127
- const r = toolCallToBoardEditOp({
126
+ test('modifyScene: 다중 root 속성 변경', () => {
127
+ const r = toolCallToSceneEditOp({
128
128
  id: '1',
129
- name: 'modifyBoard',
129
+ name: 'modifyScene',
130
130
  arguments: { patch: { fillStyle: '#0a1929', name: 'Production', width: 1920 } }
131
131
  } as any)
132
132
  expect(r).toEqual({
133
- op: 'modifyBoard',
133
+ op: 'modifyScene',
134
134
  patch: { fillStyle: '#0a1929', name: 'Production', width: 1920 }
135
135
  })
136
136
  })
137
137
 
138
138
  // Phase 2 — Scene 조작 tool dispatcher
139
139
  test('alignComponents: 정상', () => {
140
- const r = toolCallToBoardEditOp({
140
+ const r = toolCallToSceneEditOp({
141
141
  id: '1',
142
142
  name: 'alignComponents',
143
143
  arguments: { refids: [1, 2, 3], direction: 'left' }
@@ -147,7 +147,7 @@ describe('toolCallToBoardEditOp', () => {
147
147
 
148
148
  test('alignComponents: 잘못된 direction → null', () => {
149
149
  expect(
150
- toolCallToBoardEditOp({
150
+ toolCallToSceneEditOp({
151
151
  id: '1',
152
152
  name: 'alignComponents',
153
153
  arguments: { refids: [1, 2], direction: 'sideways' }
@@ -157,7 +157,7 @@ describe('toolCallToBoardEditOp', () => {
157
157
 
158
158
  test('alignComponents: refids 비어있음 → null', () => {
159
159
  expect(
160
- toolCallToBoardEditOp({
160
+ toolCallToSceneEditOp({
161
161
  id: '1',
162
162
  name: 'alignComponents',
163
163
  arguments: { refids: [], direction: 'left' }
@@ -166,7 +166,7 @@ describe('toolCallToBoardEditOp', () => {
166
166
  })
167
167
 
168
168
  test('alignComponents: refids 안의 non-number 무시', () => {
169
- const r = toolCallToBoardEditOp({
169
+ const r = toolCallToSceneEditOp({
170
170
  id: '1',
171
171
  name: 'alignComponents',
172
172
  arguments: { refids: [1, 'foo', 2, null], direction: 'center' }
@@ -175,7 +175,7 @@ describe('toolCallToBoardEditOp', () => {
175
175
  })
176
176
 
177
177
  test('distributeComponents: 정상', () => {
178
- const r = toolCallToBoardEditOp({
178
+ const r = toolCallToSceneEditOp({
179
179
  id: '1',
180
180
  name: 'distributeComponents',
181
181
  arguments: { refids: [1, 2, 3], axis: 'horizontal' }
@@ -185,7 +185,7 @@ describe('toolCallToBoardEditOp', () => {
185
185
 
186
186
  test('distributeComponents: 잘못된 axis → null', () => {
187
187
  expect(
188
- toolCallToBoardEditOp({
188
+ toolCallToSceneEditOp({
189
189
  id: '1',
190
190
  name: 'distributeComponents',
191
191
  arguments: { refids: [1, 2, 3], axis: 'diagonal' }
@@ -195,14 +195,14 @@ describe('toolCallToBoardEditOp', () => {
195
195
 
196
196
  test('groupComponents: 2개 이상 필수', () => {
197
197
  expect(
198
- toolCallToBoardEditOp({
198
+ toolCallToSceneEditOp({
199
199
  id: '1',
200
200
  name: 'groupComponents',
201
201
  arguments: { refids: [1] }
202
202
  } as any)
203
203
  ).toBeNull()
204
204
  expect(
205
- toolCallToBoardEditOp({
205
+ toolCallToSceneEditOp({
206
206
  id: '1',
207
207
  name: 'groupComponents',
208
208
  arguments: { refids: [1, 2] }
@@ -212,14 +212,14 @@ describe('toolCallToBoardEditOp', () => {
212
212
 
213
213
  test('ungroupComponent: refid number 필수', () => {
214
214
  expect(
215
- toolCallToBoardEditOp({
215
+ toolCallToSceneEditOp({
216
216
  id: '1',
217
217
  name: 'ungroupComponent',
218
218
  arguments: { refid: 5 }
219
219
  } as any)
220
220
  ).toEqual({ op: 'ungroup', refid: 5 })
221
221
  expect(
222
- toolCallToBoardEditOp({
222
+ toolCallToSceneEditOp({
223
223
  id: '1',
224
224
  name: 'ungroupComponent',
225
225
  arguments: {}
@@ -229,7 +229,7 @@ describe('toolCallToBoardEditOp', () => {
229
229
 
230
230
  test('changeZorder: 4 direction 모두', () => {
231
231
  for (const d of ['front', 'back', 'forward', 'backward'] as const) {
232
- const r = toolCallToBoardEditOp({
232
+ const r = toolCallToSceneEditOp({
233
233
  id: '1',
234
234
  name: 'changeZorder',
235
235
  arguments: { refid: 1, direction: d }
@@ -240,7 +240,7 @@ describe('toolCallToBoardEditOp', () => {
240
240
 
241
241
  test('changeZorder: 잘못된 direction → null', () => {
242
242
  expect(
243
- toolCallToBoardEditOp({
243
+ toolCallToSceneEditOp({
244
244
  id: '1',
245
245
  name: 'changeZorder',
246
246
  arguments: { refid: 1, direction: 'sideways' }
@@ -248,9 +248,9 @@ describe('toolCallToBoardEditOp', () => {
248
248
  ).toBeNull()
249
249
  })
250
250
 
251
- // C-1 — ephemeral action tool dispatcher (toolCallToBoardActionOp 별도)
252
- test('toolCallToBoardActionOp — selectComponents 정상', () => {
253
- const r = toolCallToBoardActionOp({
251
+ // C-1 — ephemeral action tool dispatcher (toolCallToSceneActionOp 별도)
252
+ test('toolCallToSceneActionOp — selectComponents 정상', () => {
253
+ const r = toolCallToSceneActionOp({
254
254
  id: '1',
255
255
  name: 'selectComponents',
256
256
  arguments: { refids: [1, 2, 3] }
@@ -258,8 +258,8 @@ describe('toolCallToBoardEditOp', () => {
258
258
  expect(r).toEqual({ action: 'selectComponents', refids: [1, 2, 3] })
259
259
  })
260
260
 
261
- test('toolCallToBoardActionOp — selectComponents 빈 배열도 OK (deselect)', () => {
262
- const r = toolCallToBoardActionOp({
261
+ test('toolCallToSceneActionOp — selectComponents 빈 배열도 OK (deselect)', () => {
262
+ const r = toolCallToSceneActionOp({
263
263
  id: '1',
264
264
  name: 'selectComponents',
265
265
  arguments: { refids: [] }
@@ -267,8 +267,8 @@ describe('toolCallToBoardEditOp', () => {
267
267
  expect(r).toEqual({ action: 'selectComponents', refids: [] })
268
268
  })
269
269
 
270
- test('toolCallToBoardActionOp — selectComponents non-number 무시', () => {
271
- const r = toolCallToBoardActionOp({
270
+ test('toolCallToSceneActionOp — selectComponents non-number 무시', () => {
271
+ const r = toolCallToSceneActionOp({
272
272
  id: '1',
273
273
  name: 'selectComponents',
274
274
  arguments: { refids: [1, 'foo', 2] }
@@ -276,9 +276,9 @@ describe('toolCallToBoardEditOp', () => {
276
276
  expect(r).toEqual({ action: 'selectComponents', refids: [1, 2] })
277
277
  })
278
278
 
279
- test('toolCallToBoardActionOp — centerToComponent + animated', () => {
279
+ test('toolCallToSceneActionOp — centerToComponent + animated', () => {
280
280
  expect(
281
- toolCallToBoardActionOp({
281
+ toolCallToSceneActionOp({
282
282
  id: '1',
283
283
  name: 'centerToComponent',
284
284
  arguments: { refid: 7, animated: false }
@@ -286,9 +286,9 @@ describe('toolCallToBoardEditOp', () => {
286
286
  ).toEqual({ action: 'centerToComponent', refid: 7, animated: false })
287
287
  })
288
288
 
289
- test('toolCallToBoardActionOp — centerToComponent refid 누락 → null', () => {
289
+ test('toolCallToSceneActionOp — centerToComponent refid 누락 → null', () => {
290
290
  expect(
291
- toolCallToBoardActionOp({
291
+ toolCallToSceneActionOp({
292
292
  id: '1',
293
293
  name: 'centerToComponent',
294
294
  arguments: {}
@@ -296,15 +296,15 @@ describe('toolCallToBoardEditOp', () => {
296
296
  ).toBeNull()
297
297
  })
298
298
 
299
- test('toolCallToBoardActionOp — fitToView 인자 없음 OK', () => {
299
+ test('toolCallToSceneActionOp — fitToView 인자 없음 OK', () => {
300
300
  expect(
301
- toolCallToBoardActionOp({ id: '1', name: 'fitToView', arguments: {} } as any)
301
+ toolCallToSceneActionOp({ id: '1', name: 'fitToView', arguments: {} } as any)
302
302
  ).toEqual({ action: 'fitToView' })
303
303
  })
304
304
 
305
- test('toolCallToBoardActionOp — fitToView 잘못된 mode 는 무시', () => {
305
+ test('toolCallToSceneActionOp — fitToView 잘못된 mode 는 무시', () => {
306
306
  expect(
307
- toolCallToBoardActionOp({
307
+ toolCallToSceneActionOp({
308
308
  id: '1',
309
309
  name: 'fitToView',
310
310
  arguments: { mode: 'diagonal' }
@@ -312,16 +312,16 @@ describe('toolCallToBoardEditOp', () => {
312
312
  ).toEqual({ action: 'fitToView' }) // mode 키 자체가 빠짐
313
313
  })
314
314
 
315
- test('toolCallToBoardActionOp — setSceneMode edit/view 만', () => {
315
+ test('toolCallToSceneActionOp — setSceneMode edit/view 만', () => {
316
316
  expect(
317
- toolCallToBoardActionOp({
317
+ toolCallToSceneActionOp({
318
318
  id: '1',
319
319
  name: 'setSceneMode',
320
320
  arguments: { mode: 'edit' }
321
321
  } as any)
322
322
  ).toEqual({ action: 'setSceneMode', mode: 'edit' })
323
323
  expect(
324
- toolCallToBoardActionOp({
324
+ toolCallToSceneActionOp({
325
325
  id: '1',
326
326
  name: 'setSceneMode',
327
327
  arguments: { mode: 'something' }
@@ -330,26 +330,26 @@ describe('toolCallToBoardEditOp', () => {
330
330
  })
331
331
 
332
332
  test('replaceBoard: 정상', () => {
333
- const r = toolCallToBoardEditOp({
333
+ const r = toolCallToSceneEditOp({
334
334
  id: '1',
335
335
  name: 'replaceBoard',
336
336
  arguments: { width: 1920, height: 1080, components: [{ type: 'rect' }] }
337
337
  } as any)
338
338
  expect(r?.op).toBe('replace')
339
339
  if (r && r.op === 'replace') {
340
- expect(r.board.width).toBe(1920)
341
- expect(r.board.components).toHaveLength(1)
340
+ expect(r.model.width).toBe(1920)
341
+ expect(r.model.components).toHaveLength(1)
342
342
  }
343
343
  })
344
344
 
345
345
  test('replaceBoard: components 누락 → null', () => {
346
- const r = toolCallToBoardEditOp({ id: '1', name: 'replaceBoard', arguments: {} } as any)
346
+ const r = toolCallToSceneEditOp({ id: '1', name: 'replaceBoard', arguments: {} } as any)
347
347
  expect(r).toBeNull()
348
348
  })
349
349
 
350
350
  // Sugar layout — arrangeInGrid/Row/Column dispatcher
351
351
  test('arrangeInGrid: 정상 — refids + cols + 기본값', () => {
352
- const r = toolCallToBoardEditOp({
352
+ const r = toolCallToSceneEditOp({
353
353
  id: '1',
354
354
  name: 'arrangeInGrid',
355
355
  arguments: { refids: [1, 2, 3, 4], cols: 2 }
@@ -362,7 +362,7 @@ describe('toolCallToBoardEditOp', () => {
362
362
  })
363
363
 
364
364
  test('arrangeInGrid: gap + anchor 반영', () => {
365
- const r = toolCallToBoardEditOp({
365
+ const r = toolCallToSceneEditOp({
366
366
  id: '1',
367
367
  name: 'arrangeInGrid',
368
368
  arguments: {
@@ -380,14 +380,14 @@ describe('toolCallToBoardEditOp', () => {
380
380
 
381
381
  test('arrangeInGrid: cols 누락 / refids 부족 → null', () => {
382
382
  expect(
383
- toolCallToBoardEditOp({
383
+ toolCallToSceneEditOp({
384
384
  id: '1',
385
385
  name: 'arrangeInGrid',
386
386
  arguments: { refids: [1, 2] }
387
387
  } as any)
388
388
  ).toBeNull()
389
389
  expect(
390
- toolCallToBoardEditOp({
390
+ toolCallToSceneEditOp({
391
391
  id: '1',
392
392
  name: 'arrangeInGrid',
393
393
  arguments: { refids: [1], cols: 2 }
@@ -397,7 +397,7 @@ describe('toolCallToBoardEditOp', () => {
397
397
 
398
398
  test('arrangeInGrid: cols 가 1 미만 → null', () => {
399
399
  expect(
400
- toolCallToBoardEditOp({
400
+ toolCallToSceneEditOp({
401
401
  id: '1',
402
402
  name: 'arrangeInGrid',
403
403
  arguments: { refids: [1, 2], cols: 0 }
@@ -406,7 +406,7 @@ describe('toolCallToBoardEditOp', () => {
406
406
  })
407
407
 
408
408
  test('arrangeInRow: 정상 — refids 만 있어도 OK', () => {
409
- const r = toolCallToBoardEditOp({
409
+ const r = toolCallToSceneEditOp({
410
410
  id: '1',
411
411
  name: 'arrangeInRow',
412
412
  arguments: { refids: [1, 2, 3] }
@@ -418,7 +418,7 @@ describe('toolCallToBoardEditOp', () => {
418
418
  })
419
419
 
420
420
  test('arrangeInRow: align + gap', () => {
421
- const r = toolCallToBoardEditOp({
421
+ const r = toolCallToSceneEditOp({
422
422
  id: '1',
423
423
  name: 'arrangeInRow',
424
424
  arguments: { refids: [1, 2], align: 'center', gap: 30 }
@@ -430,7 +430,7 @@ describe('toolCallToBoardEditOp', () => {
430
430
  })
431
431
 
432
432
  test('arrangeInRow: 잘못된 align 은 무시 (drop)', () => {
433
- const r = toolCallToBoardEditOp({
433
+ const r = toolCallToSceneEditOp({
434
434
  id: '1',
435
435
  name: 'arrangeInRow',
436
436
  arguments: { refids: [1, 2], align: 'top' }
@@ -441,7 +441,7 @@ describe('toolCallToBoardEditOp', () => {
441
441
  })
442
442
 
443
443
  test('arrangeInColumn: 정상', () => {
444
- const r = toolCallToBoardEditOp({
444
+ const r = toolCallToSceneEditOp({
445
445
  id: '1',
446
446
  name: 'arrangeInColumn',
447
447
  arguments: { refids: [1, 2], align: 'end', gap: 5 }
@@ -453,14 +453,14 @@ describe('toolCallToBoardEditOp', () => {
453
453
 
454
454
  test('arrangeInRow/Column: refids < 2 → null', () => {
455
455
  expect(
456
- toolCallToBoardEditOp({
456
+ toolCallToSceneEditOp({
457
457
  id: '1',
458
458
  name: 'arrangeInRow',
459
459
  arguments: { refids: [1] }
460
460
  } as any)
461
461
  ).toBeNull()
462
462
  expect(
463
- toolCallToBoardEditOp({
463
+ toolCallToSceneEditOp({
464
464
  id: '1',
465
465
  name: 'arrangeInColumn',
466
466
  arguments: { refids: [] }
@@ -476,7 +476,7 @@ describe('toolCallToBoardEditOp', () => {
476
476
 
477
477
  // Prefab — addPrefab dispatcher
478
478
  test('addPrefab: 정상 — registry 의 build 호출 + add op 으로 매핑', () => {
479
- const r = toolCallToBoardEditOp({
479
+ const r = toolCallToSceneEditOp({
480
480
  id: '1',
481
481
  name: 'addPrefab',
482
482
  arguments: {
@@ -500,7 +500,7 @@ describe('toolCallToBoardEditOp', () => {
500
500
  })
501
501
 
502
502
  test('addPrefab: width/height override', () => {
503
- const r = toolCallToBoardEditOp({
503
+ const r = toolCallToSceneEditOp({
504
504
  id: '1',
505
505
  name: 'addPrefab',
506
506
  arguments: { name: 'monitor-card', left: 0, top: 0, width: 300, height: 180 }
@@ -512,7 +512,7 @@ describe('toolCallToBoardEditOp', () => {
512
512
  })
513
513
 
514
514
  test('addPrefab: 등록되지 않은 name → null', () => {
515
- const r = toolCallToBoardEditOp({
515
+ const r = toolCallToSceneEditOp({
516
516
  id: '1',
517
517
  name: 'addPrefab',
518
518
  arguments: { name: 'no-such-prefab', left: 0, top: 0 }
@@ -522,7 +522,7 @@ describe('toolCallToBoardEditOp', () => {
522
522
 
523
523
  test('addPrefab: name 누락 → null', () => {
524
524
  expect(
525
- toolCallToBoardEditOp({
525
+ toolCallToSceneEditOp({
526
526
  id: '1',
527
527
  name: 'addPrefab',
528
528
  arguments: { left: 0, top: 0 }
@@ -532,14 +532,14 @@ describe('toolCallToBoardEditOp', () => {
532
532
 
533
533
  test('addPrefab: 좌표 누락 → null', () => {
534
534
  expect(
535
- toolCallToBoardEditOp({
535
+ toolCallToSceneEditOp({
536
536
  id: '1',
537
537
  name: 'addPrefab',
538
538
  arguments: { name: 'monitor-card' }
539
539
  } as any)
540
540
  ).toBeNull()
541
541
  expect(
542
- toolCallToBoardEditOp({
542
+ toolCallToSceneEditOp({
543
543
  id: '1',
544
544
  name: 'addPrefab',
545
545
  arguments: { name: 'monitor-card', left: 0 }
@@ -548,12 +548,12 @@ describe('toolCallToBoardEditOp', () => {
548
548
  })
549
549
 
550
550
  test('알 수 없는 tool name → null', () => {
551
- const r = toolCallToBoardEditOp({ id: '1', name: 'unknownTool', arguments: {} } as any)
551
+ const r = toolCallToSceneEditOp({ id: '1', name: 'unknownTool', arguments: {} } as any)
552
552
  expect(r).toBeNull()
553
553
  })
554
554
 
555
555
  test('arguments 누락도 안전', () => {
556
- const r = toolCallToBoardEditOp({ id: '1', name: 'addComponent' } as any)
556
+ const r = toolCallToSceneEditOp({ id: '1', name: 'addComponent' } as any)
557
557
  expect(r).toBeNull()
558
558
  })
559
559
  })
@@ -863,8 +863,8 @@ describe('buildBoardEditTools — refid 기반 tool 이름 (식별자 정책 회
863
863
  'importBoardAsync',
864
864
  'listImportAdapters',
865
865
  'materializeImportSession',
866
- 'modifyBoard',
867
866
  'modifyComponentByRefid',
867
+ 'modifyScene',
868
868
  'removeComponentByRefid',
869
869
  'replaceBoard',
870
870
  'selectComponents',
@@ -951,15 +951,15 @@ describe('buildBoardEditTools — refid 기반 tool 이름 (식별자 정책 회
951
951
  expect(t.parameters.properties.mode.enum).toEqual(['edit', 'view'])
952
952
  })
953
953
 
954
- test('modifyBoard 는 patch (object) 필수', () => {
954
+ test('modifyScene 는 patch (object) 필수', () => {
955
955
  const tools = buildBoardEditTools([])
956
- const t = tools.find(x => x.name === 'modifyBoard')!
956
+ const t = tools.find(x => x.name === 'modifyScene')!
957
957
  expect(t.parameters.required).toEqual(['patch'])
958
958
  expect(t.parameters.properties.patch.type).toBe('object')
959
959
  })
960
960
 
961
- test('isWriteTool 가 modifyBoard 인식', () => {
962
- expect(isWriteTool('modifyBoard')).toBe(true)
961
+ test('isWriteTool 가 modifyScene 인식', () => {
962
+ expect(isWriteTool('modifyScene')).toBe(true)
963
963
  })
964
964
 
965
965
  test('getSelection 은 인자 없음', () => {
@@ -1554,7 +1554,7 @@ describe('executeReadTool — getAtmosphereGuide (3D 분위기 합성 primer)',
1554
1554
  expect(r.archetypes).toHaveProperty('surreal')
1555
1555
  })
1556
1556
 
1557
- test('각 archetype 은 description + patch 보유 (modifyBoard patch 그대로 사용 가능)', () => {
1557
+ test('각 archetype 은 description + patch 보유 (modifyScene patch 그대로 사용 가능)', () => {
1558
1558
  const r = executeReadTool(
1559
1559
  { id: '1', name: 'getAtmosphereGuide', arguments: {} } as any,
1560
1560
  null,