@pixel-normal-edit/mcp 2.0.7 → 2.0.10

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 (51) hide show
  1. package/domains/art-tree/advanced_lessons.js +11 -11
  2. package/domains/art-tree/advanced_tools.js +12 -12
  3. package/domains/art-tree/analysis_lessons.js +32 -0
  4. package/domains/art-tree/analysis_shapes.js +146 -0
  5. package/domains/art-tree/analysis_tools.js +49 -0
  6. package/domains/art-tree/hidden_lessons.js +3 -3
  7. package/domains/art-tree/index.js +10 -0
  8. package/domains/art-tree/layer_lessons.js +32 -0
  9. package/domains/art-tree/layer_shapes.js +117 -0
  10. package/domains/art-tree/layer_tools.js +43 -0
  11. package/domains/art-tree/lessons.js +19 -19
  12. package/domains/art-tree/light_lessons.js +3 -3
  13. package/domains/art-tree/light_shapes.js +5 -5
  14. package/domains/art-tree/material_lessons.js +71 -0
  15. package/domains/art-tree/material_shapes.js +130 -0
  16. package/domains/art-tree/material_tools.js +49 -0
  17. package/domains/art-tree/perspective_lessons.js +1 -1
  18. package/domains/art-tree/perspective_tools.js +1 -1
  19. package/domains/art-tree/sky_lessons_1.js +82 -0
  20. package/domains/art-tree/sky_shapes_1.js +68 -0
  21. package/domains/art-tree/sky_tools.js +51 -0
  22. package/domains/art-tree/surface_lessons.js +7 -7
  23. package/domains/art-tree/tools.js +27 -27
  24. package/domains/art-tree/transform_lessons_1.js +2 -2
  25. package/domains/art-tree/transform_lessons_2.js +4 -4
  26. package/domains/art-tree/transform_tools.js +8 -8
  27. package/domains/art-tree/vocab_lessons.js +32 -0
  28. package/domains/art-tree/vocab_shapes.js +116 -0
  29. package/domains/art-tree/vocab_tools.js +41 -0
  30. package/index.js +4 -0
  31. package/package.json +1 -1
  32. package/rules/README.md +403 -0
  33. package/rules/index.js +34 -0
  34. package/rules/prerequisites.js +145 -0
  35. package/rules/rules.js +111 -0
  36. package/rules/workflow.js +200 -0
  37. package/tools/{anchors.js → anchor-tools.js} +1 -1
  38. package/tools/{animation.js → animation-tools.js} +1 -1
  39. package/tools/{canvas.js → canvas-tools.js} +1 -1
  40. package/tools/{colors.js → color-tools.js} +1 -1
  41. package/tools/{drawing.js → drawing-tools.js} +1 -1
  42. package/tools/{filters.js → filter-tools.js} +1 -1
  43. package/tools/{health.js → health-tools.js} +1 -1
  44. package/tools/{history.js → history-tools.js} +1 -1
  45. package/tools/index.js +31 -13
  46. package/tools/layer-tools.js +80 -0
  47. package/tools/{modes.js → mode-tools.js} +1 -1
  48. package/tools/{query.js → query-tools.js} +1 -1
  49. package/tools/{region.js → region-tools.js} +1 -1
  50. package/tools/{sprite.js → sprite-tools.js} +1 -1
  51. package/tools/{workspace.js → workspace-tools.js} +2 -3
@@ -0,0 +1,403 @@
1
+ # Rules Module — Báo cáo hoạt động
2
+
3
+ ## Tổng quan
4
+
5
+ Module `rules/` là **bộ não điều khiển** của MCP Firebase Bridge. Nó đảm bảo agent AI **không thể làm bậy** — mọi thao tác vẽ đều phải tuân theo quy trình đã định sẵn.
6
+
7
+ ---
8
+
9
+ ## Cấu trúc thư mục
10
+
11
+ ```
12
+ rules/
13
+ ├── index.js # Module aggregator — import tất cả và export registerAll()
14
+ ├── rules.js # Định nghĩa rules: naming, workflow steps, constraints
15
+ ├── workflow.js # Workflow engine — quản lý trạng thái từng bước
16
+ └── prerequisites.js # 7 MCP Tools để agent tương tác với workflow
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Luồng hoạt động (Workflow)
22
+
23
+ ### 1. Agent bắt đầu bằng `workflow_start`
24
+
25
+ ```
26
+ Agent → workflow_start()
27
+
28
+ Workflow Engine khởi tạo 9 bước:
29
+ [create_canvas → name_canvas → resize_canvas → enable_animation →
30
+ setup_layers → prepare_colors → draw → review → finalize]
31
+
32
+ Trả về: "Bước hiện tại: Tạo canvas"
33
+ ```
34
+
35
+ ### 2. Agent thực hiện từng bước
36
+
37
+ Mỗi bước có **3 tool** liên quan:
38
+
39
+ | Tool | Mục đích | Khi nào dùng |
40
+ |------|----------|--------------|
41
+ | `workflow_validate` | Kiểm tra có được phép làm bước này không | **TRƯỚC** mỗi thao tác |
42
+ | `*_tools` (vd: `canvas_resize`) | Thực hiện thao tác thật | Sau khi validate OK |
43
+ | `workflow_advance` | Đánh dấu hoàn thành, chuyển bước tiếp theo | **SAU** khi thao tác thành công |
44
+
45
+ **Ví dụ thực tế — Bước "Đặt tên canvas":**
46
+
47
+ ```
48
+ Agent → workflow_validate(stepId: "name_canvas")
49
+
50
+ Workflow Engine kiểm tra:
51
+ - Đang ở bước 2? ✓
52
+ - Bước 1 đã hoàn thành? ✓
53
+
54
+ Trả về: "✅ Bạn có thể thực hiện name_canvas"
55
+
56
+ Agent → validate_canvas_name(name: "Bức tranh 1")
57
+
58
+ Trả về: "✅ Tên hợp lệ!"
59
+
60
+ Agent → workspace_rename_tab(tabId: "...", name: "Bức tranh 1")
61
+
62
+ Thực hiện đổi tên thành công
63
+
64
+ Agent → workflow_advance()
65
+
66
+ Workflow Engine:
67
+ - Đánh dấu "name_canvas" = completed
68
+ - Chuyển sang bước 3: "Resize canvas"
69
+
70
+ Trả về: "✅ Hoàn thành: Đặt tên canvas. Bước tiếp theo: Resize canvas"
71
+ ```
72
+
73
+ ### 3. Nếu agent làm sai thứ tự → BỊ CHẶN
74
+
75
+ ```
76
+ Agent → draw_pixel(x: 10, y: 10, color: "#ff0000") # ❌ Vẽ trước khi tạo canvas!
77
+
78
+ (Nếu có middleware kiểm tra workflow)
79
+
80
+ Trả về: "⛔ Bạn chưa thể thực hiện 'draw'.
81
+ Trước hết hãy hoàn thành: Tạo canvas"
82
+ ```
83
+
84
+ ---
85
+
86
+ ## 7 Workflow Tools (trong `prerequisites.js`)
87
+
88
+ ### 1. `workflow_start`
89
+ **Mục đích:** Khởi tạo workflow mới
90
+ **Tham số:** Không có
91
+ **Trả về:** Trạng thái workflow ban đầu + bước đầu tiên cần làm
92
+
93
+ ```json
94
+ {
95
+ "content": [{
96
+ "type": "text",
97
+ "text": "🚀 Workflow đã bắt đầu!\n📋 Tiến trình vẽ:\n⬜ Tạo canvas\n🔄 Đặt tên canvas ← ĐANG LÀM\n..."
98
+ }]
99
+ }
100
+ ```
101
+
102
+ ### 2. `workflow_status`
103
+ **Mục đích:** Xem tiến trình hiện tại
104
+ **Tham số:** Không có
105
+ **Trả về:** Danh sách các bước với trạng thái (✅/🔄/⬜)
106
+
107
+ ### 3. `workflow_advance`
108
+ **Mục đích:** Đánh dấu hoàn thành bước hiện tại, chuyển sang bước tiếp theo
109
+ **Tham số:** Không có
110
+ **Trả về:** Thông báo bước vừa hoàn thành + bước tiếp theo
111
+
112
+ ### 4. `workflow_validate`
113
+ **Mục đích:** Kiểm tra agent có được phép thực hiện hành động không
114
+ **Tham số:**
115
+ - `stepId` (string): ID bước muốn kiểm tra (vd: "draw", "resize_canvas")
116
+
117
+ **Trả về:**
118
+ - Nếu OK: `"✅ Bạn có thể thực hiện 'draw'. Hãy tiếp tục!"`
119
+ - Nếu sai thứ tự: `"⛔ Bạn chưa thể thực hiện 'draw'. Trước hết hãy hoàn thành: Tạo canvas"`
120
+
121
+ ### 5. `workflow_reset`
122
+ **Mục đích:** Reset workflow về đầu (xóa toàn bộ tiến trình)
123
+ **Tham số:** Không có
124
+ **Trả về:** `"🔄 Workflow đã được reset. Hãy bắt đầu lại từ đầu."`
125
+
126
+ ### 6. `validate_canvas_name`
127
+ **Mục đích:** Kiểm tra tên canvas có hợp lệ không
128
+ **Tham số:**
129
+ - `name` (string): Tên canvas muốn kiểm tra
130
+
131
+ **Quy tắc:**
132
+ - 3-64 ký tự
133
+ - Chỉ gồm chữ, số, `_`, `-`, khoảng trắng
134
+ - Ví dụ hợp lệ: "Bức_tranh_1", "My Canvas 2024"
135
+
136
+ ### 7. `validate_canvas_size`
137
+ **Mục đích:** Kiểm tra kích thước canvas có nằm trong giới hạn không
138
+ **Tham số:**
139
+ - `width` (int): Chiều rộng
140
+ - `height` (int): Chiều cao
141
+
142
+ **Giới hạn:** 8x8 đến 1024x1024 pixels
143
+
144
+ ---
145
+
146
+ ## 9 Workflow Steps (định nghĩa trong `rules.js`)
147
+
148
+ | # | Step ID | Label | Description |
149
+ |---|---------|-------|-------------|
150
+ | 1 | `create_canvas` | Tạo canvas | Tạo tab mới với kích thước phù hợp |
151
+ | 2 | `name_canvas` | Đặt tên canvas | Đặt tên cho canvas (3-64 ký tự) |
152
+ | 3 | `resize_canvas` | Resize canvas | Điều chỉnh kích thước canvas nếu cần |
153
+ | 4 | `enable_animation` | Bật animation | Bật chế độ animation nếu cần nhiều frame |
154
+ | 5 | `setup_layers` | Thiết lập layers | Tạo/sắp xếp layers trước khi vẽ |
155
+ | 6 | `prepare_colors` | Chuẩn bị màu sắc | Chọn màu chính/phụ trước khi vẽ |
156
+ | 7 | `draw` | Vẽ | Thực hiện vẽ theo đúng kỹ thuật |
157
+ | 8 | `review` | Kiểm tra | Xem lại kết quả sau khi vẽ |
158
+ | 9 | `finalize` | Hoàn tất | Lưu và hoàn tất tác phẩm |
159
+
160
+ ---
161
+
162
+ ## Các loại Rules (trong `rules.js`)
163
+
164
+ ### 1. Naming Rules (`NAMING_RULES`)
165
+
166
+ Quy tắc đặt tên cho các đối tượng:
167
+
168
+ | Object | Pattern | Example |
169
+ |--------|---------|---------|
170
+ | Canvas/Tab | `^[A-Za-z0-9_\-\sÀ-ỹ]{3,64}$` | "Bức_tranh_1" |
171
+ | Stamp | `^[a-z][a-z0-9_]{2,32}$` | "my_tree_01" |
172
+ | Anchor | `^[a-z][a-z0-9_]{2,32}$` | "head_top" |
173
+
174
+ ### 2. Workflow Steps (`WORKFLOW_STEPS`)
175
+
176
+ Danh sách 9 bước bắt buộc (xem bảng ở mục trên).
177
+
178
+ ### 3. Drawing Constraints (`DRAWING_CONSTRAINTS`)
179
+
180
+ | Constraint | Value |
181
+ |------------|-------|
182
+ | Max canvas size | 1024x1024 |
183
+ | Min canvas size | 8x8 |
184
+ | Allowed colors | Tất cả hex colors |
185
+ | Max stamp name length | 32 ký tự |
186
+ | Max anchor name length | 32 ký tự |
187
+
188
+ ---
189
+
190
+ ## Workflow Engine (`workflow.js`)
191
+
192
+ ### State Management
193
+
194
+ Workflow engine lưu trạng thái **in-memory** theo session:
195
+
196
+ ```javascript
197
+ sessions = new Map([
198
+ "session-id-1": {
199
+ currentStepIndex: 2,
200
+ steps: [
201
+ { id: "create_canvas", label: "Tạo canvas", status: "completed" },
202
+ { id: "name_canvas", label: "Đặt tên canvas", status: "completed" },
203
+ { id: "resize_canvas", label: "Resize canvas", status: "in_progress" },
204
+ // ...
205
+ ],
206
+ completedSteps: ["create_canvas", "name_canvas"],
207
+ startedAt: 1234567890
208
+ }
209
+ ])
210
+ ```
211
+
212
+ ### Các hàm chính
213
+
214
+ | Hàm | Mục đích |
215
+ |------|----------|
216
+ | `start(sessionId)` | Khởi tạo workflow mới |
217
+ | `getState(sessionId)` | Lấy toàn bộ trạng thái |
218
+ | `getCurrentStep(sessionId)` | Lấy bước hiện tại |
219
+ | `validateStep(sessionId, stepId)` | Kiểm tra có được phép làm bước này không |
220
+ | `advance(sessionId)` | Hoàn thành bước hiện tại, chuyển sang bước tiếp |
221
+ | `reset(sessionId)` | Reset workflow về đầu |
222
+ | `getProgressReport(sessionId)` | Lấy báo cáo tiến trình dạng text |
223
+
224
+ ### Logic Validation
225
+
226
+ ```
227
+ validateStep(sessionId, stepId):
228
+ 1. Nếu chưa start workflow → TỪ CHỐI
229
+ 2. Nếu workflow đã hoàn thành → TỪ CHỐI
230
+ 3. Nếu stepId đã hoàn thành → CHO PHÉP (với warning)
231
+ 4. Nếu stepId đúng là bước hiện tại → CHO PHÉP
232
+ 5. Nếu stepId nằm ở tương lai → TỪ CHỐI (với hướng dẫn bước hiện tại)
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Cách sử dụng cho Agent
238
+
239
+ ### Scenario 1: Vẽ một hình tròn đơn giản
240
+
241
+ ```
242
+ 1. workflow_start()
243
+ → "Bước 1: Tạo canvas"
244
+
245
+ 2. validate_canvas_size(width: 32, height: 32)
246
+ → "✅ Kích thước 32x32 hợp lệ!"
247
+
248
+ 3. workspace_create_tab(width: 32, height: 32)
249
+ → Tạo canvas thành công
250
+
251
+ 4. workflow_validate(stepId: "name_canvas")
252
+ → "✅ Bạn có thể thực hiện name_canvas"
253
+
254
+ 5. validate_canvas_name(name: "Hình tròn")
255
+ → "✅ Tên hợp lệ!"
256
+
257
+ 6. workspace_rename_tab(tabId: "...", name: "Hình tròn")
258
+ → Đổi tên thành công
259
+
260
+ 7. workflow_advance()
261
+ → "✅ Hoàn thành: Đặt tên canvas. Bước tiếp theo: Resize canvas"
262
+
263
+ 8. workflow_validate(stepId: "resize_canvas")
264
+ → "✅ Bạn có thể thực hiện resize_canvas"
265
+
266
+ 9. canvas_resize(width: 64, height: 64)
267
+ → Resize thành công
268
+
269
+ 10. workflow_advance()
270
+ → Chuyển sang bước "Bật animation"
271
+
272
+ 11. workflow_validate(stepId: "enable_animation")
273
+ → "✅ Bạn có thể thực hiện enable_animation"
274
+
275
+ 12. animation_enable(enabled: false) # Không cần animation
276
+ → OK
277
+
278
+ 13. workflow_advance()
279
+ → Chuyển sang bước "Thiết lập layers"
280
+
281
+ 14. workflow_validate(stepId: "setup_layers")
282
+ → "✅ Bạn có thể thực hiện setup_layers"
283
+
284
+ 15. layer_add()
285
+ → Thêm layer mới
286
+
287
+ 16. workflow_advance()
288
+ → Chuyển sang bước "Chuẩn bị màu sắc"
289
+
290
+ 17. workflow_validate(stepId: "prepare_colors")
291
+ → "✅ Bạn có thể thực hiện prepare_colors"
292
+
293
+ 18. color_set(primary: "#ff0000")
294
+ → Đặt màu đỏ
295
+
296
+ 19. workflow_advance()
297
+ → Chuyển sang bước "Vẽ" ← ĐÂY LÀ BƯỚC QUAN TRỌNG
298
+
299
+ 20. workflow_validate(stepId: "draw")
300
+ → "✅ Bạn có thể thực hiện draw"
301
+
302
+ 21. draw_circle(cx: 32, cy: 32, r: 20, color: "#ff0000")
303
+ → Vẽ hình tròn thành công
304
+
305
+ 22. workflow_advance()
306
+ → Chuyển sang bước "Kiểm tra"
307
+
308
+ 23. workflow_validate(stepId: "review")
309
+ → "✅ Bạn có thể thực hiện review"
310
+
311
+ 24. query_snapshot()
312
+ → Xem kết quả vẽ
313
+
314
+ 25. workflow_advance()
315
+ → Chuyển sang bước "Hoàn tất"
316
+
317
+ 26. workflow_validate(stepId: "finalize")
318
+ → "✅ Bạn có thể thực hiện finalize"
319
+
320
+ 27. workspace_save()
321
+ → Lưu tác phẩm
322
+
323
+ 28. workflow_advance()
324
+ → "🎉 Hoàn tất tất cả các bước!"
325
+ ```
326
+
327
+ ### Scenario 2: Agent cố gắng vẽ trước khi tạo canvas
328
+
329
+ ```
330
+ 1. workflow_start()
331
+ → "Bước 1: Tạo canvas"
332
+
333
+ 2. draw_pixel(x: 10, y: 10, color: "#ff0000") # ❌ Sai thứ tự!
334
+ → (Nếu có middleware kiểm tra)
335
+ → "⛔ Bạn chưa thể thực hiện 'draw'.
336
+ Trước hết hãy hoàn thành: Tạo canvas"
337
+ ```
338
+
339
+ ---
340
+
341
+ ## Lưu ý quan trọng
342
+
343
+ 1. **Workflow là per-session:** Mỗi session có workflow riêng, không ảnh hưởng lẫn nhau.
344
+ 2. **Có thể quay lại bước cũ:** Nếu agent đã hoàn thành bước 3 và muốn làm lại, `validateStep` sẽ cho phép nhưng có cảnh báo.
345
+ 3. **Workflow không tự động chặn tool:** Tool `draw_pixel` vẫn chạy được nếu agent gọi trực tiếp. Tuy nhiên, agent được hướng dẫn **PHẢI** gọi `workflow_validate` trước mỗi thao tác.
346
+ 4. **Có thể reset:** Dùng `workflow_reset` để bắt đầu lại từ đầu nếu cần.
347
+
348
+ ---
349
+
350
+ ## Cách thêm Rule mới
351
+
352
+ ### Thêm Naming Rule mới
353
+
354
+ ```javascript
355
+ // rules.js
356
+ const NAMING_RULES = {
357
+ // ... existing rules
358
+ newObject: {
359
+ pattern: /^[a-z]{3,16}$/,
360
+ message: 'Tên phải 3-16 ký tự, chỉ chữ thường',
361
+ example: 'myobject',
362
+ },
363
+ };
364
+
365
+ // Thêm validator
366
+ function validateNewObjectName(name) {
367
+ if (!name || typeof name !== 'string') {
368
+ return { valid: false, message: 'Tên không được để trống' };
369
+ }
370
+ if (!NAMING_RULES.newObject.pattern.test(name)) {
371
+ return { valid: false, message: NAMING_RULES.newObject.message };
372
+ }
373
+ return { valid: true };
374
+ }
375
+ ```
376
+
377
+ ### Thêm Workflow Step mới
378
+
379
+ ```javascript
380
+ // rules.js
381
+ const WORKFLOW_STEPS = [
382
+ // ... existing steps
383
+ { id: 'new_step', label: 'Bước mới', description: 'Mô tả bước mới' },
384
+ ];
385
+
386
+ // prerequisites.js — Thêm tool validate nếu cần
387
+ registerTool(server, 'validate_new_step', 'Kiểm tra...', {...}, (p) => {...});
388
+ ```
389
+
390
+ ---
391
+
392
+ ## Tóm tắt
393
+
394
+ Module `rules/` đảm bảo:
395
+
396
+ ✅ Agent **bắt buộc** tuân theo thứ tự 9 bước
397
+ ✅ Tất cả tên đều **hợp lệ** theo quy tắc
398
+ ✅ Kích thước canvas **nằm trong giới hạn**
399
+ ✅ Agent **không thể bỏ qua** bước nào
400
+ ✅ Có thể **kiểm tra tiến trình** bất cứ lúc nào
401
+ ✅ Có thể **reset** nếu cần làm lại
402
+
403
+ **Mục tiêu:** Không còn tình trạng "agent muốn gì làm nấy" — mọi thao tác đều có **rule engine** giám sát.
package/rules/index.js ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * rules/index.js — Rules Module Aggregator
4
+ *
5
+ * Aggregates và export tất cả các rules, workflow engine, và prerequisite tools.
6
+ *
7
+ * Module này cung cấp:
8
+ * 1. rules.js — Định nghĩa rules (naming, constraints, validators)
9
+ * 2. workflow.js — Workflow engine (quản lý thứ tự bước)
10
+ * 3. prerequisites.js — MCP Tools cho workflow (start, status, advance, validate)
11
+ *
12
+ * Cách thêm rule mới:
13
+ * - Thêm vào rules.js (NAMING_RULES, WORKFLOW_STEPS, DRAWING_CONSTRAINTS)
14
+ * - Nếu cần logic phức tạp, tạo file mới trong rules/ và import vào đây
15
+ */
16
+
17
+ const rules = require('./rules');
18
+ const workflow = require('./workflow');
19
+ const prerequisites = require('./prerequisites');
20
+
21
+ /**
22
+ * Register tất cả workflow/prerequisite tools lên MCP server
23
+ * @param {McpServer} server
24
+ */
25
+ function registerAll(server) {
26
+ prerequisites.register(server);
27
+ }
28
+
29
+ module.exports = {
30
+ rules,
31
+ workflow,
32
+ prerequisites,
33
+ registerAll,
34
+ };
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * prerequisites.js — Prerequisites Check (Điều kiện để chạy)
4
+ *
5
+ * Đây là MCP Tool để agent gọi trước khi bắt đầu vẽ.
6
+ * Nó sẽ kiểm tra mọi điều kiện tiên quyết và trả về hướng dẫn chi tiết.
7
+ *
8
+ * QUAN TRỌNG: Agent BẮT BUỘC phải gọi tool này TRƯỚC TIÊN
9
+ * trước khi làm bất kỳ thao tác vẽ nào.
10
+ */
11
+
12
+ const { z } = require('zod');
13
+ const { validateCanvasName, validateCanvasSize, DRAWING_CONSTRAINTS, WORKFLOW_STEPS } = require('./rules');
14
+ const workflow = require('./workflow');
15
+ const { registerTool } = require('../core/server');
16
+
17
+ /**
18
+ * Register workflow/prerequisite tools on the MCP server
19
+ * @param {McpServer} server
20
+ */
21
+ function register(server) {
22
+ // ── Tool 1: workflow_start — Bắt đầu workflow ─────────────────────────
23
+ registerTool(server, 'workflow_start',
24
+ `🚀 BẮT BUỘC: Gọi tool này ĐẦU TIÊN trước khi vẽ bất cứ thứ gì.
25
+ Tool này khởi tạo một workflow vẽ với các bước tuần tự.
26
+ Agent PHẢI làm theo đúng thứ tự các bước.
27
+
28
+ Các bước workflow:
29
+ 1. create_canvas — Tạo canvas mới
30
+ 2. name_canvas — Đặt tên cho canvas
31
+ 3. resize_canvas — Resize nếu cần
32
+ 4. enable_animation — Bật animation nếu cần
33
+ 5. setup_layers — Thiết lập layers
34
+ 6. prepare_colors — Chuẩn bị màu sắc
35
+ 7. draw — Vẽ (chỉ được vẽ sau các bước trên)
36
+ 8. review — Kiểm tra kết quả
37
+ 9. finalize — Lưu và hoàn tất`,
38
+ {},
39
+ () => {
40
+ const session = require('../core/command-bus').SESSION;
41
+ const state = workflow.start(session);
42
+ return {
43
+ content: [{ type: 'text', text: `🚀 **Workflow đã bắt đầu!**\n\n${workflow.getProgressReport(session)}\n\n---\nBắt đầu với bước: **${state.steps[0].label}** → ${state.steps[0].description}` }]
44
+ };
45
+ });
46
+
47
+ // ── Tool 2: workflow_status — Xem trạng thái hiện tại ─────────────────
48
+ registerTool(server, 'workflow_status',
49
+ 'Xem tiến trình workflow hiện tại: đang ở bước nào, đã làm gì, cần làm gì tiếp theo.',
50
+ {},
51
+ () => {
52
+ const session = require('../core/command-bus').SESSION;
53
+ const report = workflow.getProgressReport(session);
54
+ const current = workflow.getCurrentStep(session);
55
+ if (!current) {
56
+ return { content: [{ type: 'text', text: '⚠️ Chưa bắt đầu workflow. Gọi **workflow_start** trước.' }] };
57
+ }
58
+ return {
59
+ content: [{
60
+ type: 'text',
61
+ text: `${report}\n\n👉 **Đang cần:** ${current.label} — ${current.description}`
62
+ }]
63
+ };
64
+ });
65
+
66
+ // ── Tool 3: workflow_advance — Hoàn thành bước hiện tại ───────────────
67
+ registerTool(server, 'workflow_advance',
68
+ '✅ Đánh dấu bước hiện tại là hoàn thành và chuyển sang bước tiếp theo. Chỉ gọi SAU KHI đã làm xong bước hiện tại.',
69
+ {},
70
+ () => {
71
+ const session = require('../core/command-bus').SESSION;
72
+ const result = workflow.advance(session);
73
+ if (!result.success) {
74
+ return { isError: true, content: [{ type: 'text', text: `❌ ${result.message}` }] };
75
+ }
76
+ if (!result.nextStep) {
77
+ return { content: [{ type: 'text', text: `🎉 ${result.message}` }] };
78
+ }
79
+ return { content: [{ type: 'text', text: result.message }] };
80
+ });
81
+
82
+ // ── Tool 4: workflow_validate — Kiểm tra trước khi gọi tool ──────────
83
+ registerTool(server, 'workflow_validate',
84
+ `🔍 Kiểm tra xem agent có được phép thực hiện một hành động nào đó không.
85
+ Gọi tool này TRƯỚC khi làm bất kỳ thao tác vẽ nào để đảm bảo đúng thứ tự workflow.
86
+
87
+ Các stepId hợp lệ:
88
+ - create_canvas
89
+ - name_canvas
90
+ - resize_canvas
91
+ - enable_animation
92
+ - setup_layers
93
+ - prepare_colors
94
+ - draw
95
+ - review
96
+ - finalize`,
97
+ { stepId: z.string().describe('ID của bước muốn kiểm tra (vd: "draw", "resize_canvas")') },
98
+ (p) => {
99
+ const session = require('../core/command-bus').SESSION;
100
+ const result = workflow.validateStep(session, p.stepId);
101
+ if (!result.allowed) {
102
+ return { isError: true, content: [{ type: 'text', text: result.message }] };
103
+ }
104
+ return { content: [{ type: 'text', text: result.message || `✅ Bạn có thể thực hiện "${p.stepId}". Hãy tiếp tục!` }] };
105
+ });
106
+
107
+ // ── Tool 5: workflow_reset — Làm lại từ đầu ──────────────────────────
108
+ registerTool(server, 'workflow_reset',
109
+ '🔄 Reset workflow về trạng thái ban đầu. Xoá toàn bộ tiến trình đã làm.',
110
+ {},
111
+ () => {
112
+ const session = require('../core/command-bus').SESSION;
113
+ workflow.reset(session);
114
+ return { content: [{ type: 'text', text: '🔄 Workflow đã được reset. Hãy bắt đầu lại từ đầu.' }] };
115
+ });
116
+
117
+ // ── Tool 6: validate_canvas_name — Kiểm tra tên canvas ───────────────
118
+ registerTool(server, 'validate_canvas_name',
119
+ `Kiểm tra tên canvas có hợp lệ không trước khi đặt.
120
+ Quy tắc: 3-64 ký tự, chỉ gồm chữ, số, _, -, khoảng trắng.
121
+ Ví dụ: "Bức_tranh_1", "My Canvas 2024"`,
122
+ { name: z.string().describe('Tên canvas muốn kiểm tra') },
123
+ (p) => {
124
+ const result = validateCanvasName(p.name);
125
+ if (!result.valid) {
126
+ return { isError: true, content: [{ type: 'text', text: `❌ ${result.message}` }] };
127
+ }
128
+ return { content: [{ type: 'text', text: `✅ Tên "${p.name}" hợp lệ!` }] };
129
+ });
130
+
131
+ // ── Tool 7: validate_canvas_size — Kiểm tra kích thước canvas ────────
132
+ registerTool(server, 'validate_canvas_size',
133
+ `Kiểm tra kích thước canvas có nằm trong giới hạn cho phép không.
134
+ Giới hạn: ${DRAWING_CONSTRAINTS.minCanvasSize.width}x${DRAWING_CONSTRAINTS.minCanvasSize.height} đến ${DRAWING_CONSTRAINTS.maxCanvasSize.width}x${DRAWING_CONSTRAINTS.maxCanvasSize.height}`,
135
+ { width: z.number().int().describe('Chiều rộng'), height: z.number().int().describe('Chiều cao') },
136
+ (p) => {
137
+ const result = validateCanvasSize(p.width, p.height);
138
+ if (!result.valid) {
139
+ return { isError: true, content: [{ type: 'text', text: `❌ ${result.message}` }] };
140
+ }
141
+ return { content: [{ type: 'text', text: `✅ Kích thước ${p.width}x${p.height} hợp lệ!` }] };
142
+ });
143
+ }
144
+
145
+ module.exports = { register };
package/rules/rules.js ADDED
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * rules.js — Core Drawing Rules & Constraints
4
+ *
5
+ * QUAN TRỌNG: Mọi function trong đây là luật BẮT BUỘC.
6
+ * Agent KHÔNG được tự ý bỏ qua hay làm sai thứ tự.
7
+ *
8
+ * Các rules được chia làm 3 loại:
9
+ * 1. naming — Quy tắc đặt tên tab/canvas
10
+ * 2. workflow — Quy tắc thứ tự các bước
11
+ * 3. drawing — Quy tắc về vẽ (kích thước, màu sắc, v.v.)
12
+ */
13
+
14
+ // ── Loại 1: Naming Rules ────────────────────────────────────────────────────
15
+ const NAMING_RULES = {
16
+ canvasTab: {
17
+ pattern: /^[A-Za-z0-9_\-\sÀ-ỹ]{3,64}$/,
18
+ message: 'Tên canvas phải từ 3-64 ký tự, chỉ gồm chữ, số, _, -, và khoảng trắng',
19
+ example: 'Bức_tranh_1',
20
+ },
21
+ stamp: {
22
+ pattern: /^[a-z][a-z0-9_]{2,32}$/,
23
+ message: 'Tên stamp phải bắt đầu bằng chữ thường, 3-32 ký tự, chỉ gồm a-z, 0-9, _',
24
+ example: 'my_tree_01',
25
+ },
26
+ anchor: {
27
+ pattern: /^[a-z][a-z0-9_]{2,32}$/,
28
+ message: 'Tên anchor phải bắt đầu bằng chữ thường, 3-32 ký tự',
29
+ example: 'head_top',
30
+ },
31
+ };
32
+
33
+ // ── Loại 2: Workflow Steps (thứ tự bắt buộc) ──────────────────────────────
34
+ const WORKFLOW_STEPS = [
35
+ { id: 'create_canvas', label: 'Tạo canvas', description: 'Tạo tab mới với kích thước phù hợp' },
36
+ { id: 'name_canvas', label: 'Đặt tên canvas', description: 'Đặt tên cho canvas (3-64 ký tự)' },
37
+ { id: 'resize_canvas', label: 'Resize canvas', description: 'Điều chỉnh kích thước canvas nếu cần' },
38
+ { id: 'enable_animation', label: 'Bật animation', description: 'Bật chế độ animation nếu cần nhiều frame' },
39
+ { id: 'setup_layers', label: 'Thiết lập layers', description: 'Tạo/sắp xếp layers trước khi vẽ' },
40
+ { id: 'prepare_colors', label: 'Chuẩn bị màu sắc', description: 'Chọn màu chính/phụ trước khi vẽ' },
41
+ { id: 'draw', label: 'Vẽ', description: 'Thực hiện vẽ theo đúng kỹ thuật' },
42
+ { id: 'review', label: 'Kiểm tra', description: 'Xem lại kết quả sau khi vẽ' },
43
+ { id: 'finalize', label: 'Hoàn tất', description: 'Lưu và hoàn tất tác phẩm' },
44
+ ];
45
+
46
+ // ── Loại 3: Drawing Constraints ─────────────────────────────────────────────
47
+ const DRAWING_CONSTRAINTS = {
48
+ maxCanvasSize: { width: 1024, height: 1024 },
49
+ minCanvasSize: { width: 8, height: 8 },
50
+ allowedColors: null, // null = all hex colors allowed
51
+ maxStampNameLength: 32,
52
+ maxAnchorNameLength: 32,
53
+ };
54
+
55
+ // ── Validator Functions ──────────────────────────────────────────────────────
56
+
57
+ /**
58
+ * Kiểm tra tên canvas có hợp lệ không
59
+ * @param {string} name
60
+ * @returns {{ valid: boolean, message?: string }}
61
+ */
62
+ function validateCanvasName(name) {
63
+ if (!name || typeof name !== 'string') {
64
+ return { valid: false, message: 'Tên canvas không được để trống' };
65
+ }
66
+ if (!NAMING_RULES.canvasTab.pattern.test(name)) {
67
+ return { valid: false, message: NAMING_RULES.canvasTab.message };
68
+ }
69
+ return { valid: true };
70
+ }
71
+
72
+ /**
73
+ * Kiểm tra tên stamp có hợp lệ không
74
+ * @param {string} name
75
+ * @returns {{ valid: boolean, message?: string }}
76
+ */
77
+ function validateStampName(name) {
78
+ if (!name || typeof name !== 'string') {
79
+ return { valid: false, message: 'Tên stamp không được để trống' };
80
+ }
81
+ if (!NAMING_RULES.stamp.pattern.test(name)) {
82
+ return { valid: false, message: NAMING_RULES.stamp.message };
83
+ }
84
+ return { valid: true };
85
+ }
86
+
87
+ /**
88
+ * Kiểm tra kích thước canvas có nằm trong giới hạn không
89
+ * @param {number} w
90
+ * @param {number} h
91
+ * @returns {{ valid: boolean, message?: string }}
92
+ */
93
+ function validateCanvasSize(w, h) {
94
+ const { minCanvasSize, maxCanvasSize } = DRAWING_CONSTRAINTS;
95
+ if (w < minCanvasSize.width || h < minCanvasSize.height) {
96
+ return { valid: false, message: `Canvas tối thiểu ${minCanvasSize.width}x${minCanvasSize.height}` };
97
+ }
98
+ if (w > maxCanvasSize.width || h > maxCanvasSize.height) {
99
+ return { valid: false, message: `Canvas tối đa ${maxCanvasSize.width}x${maxCanvasSize.height}` };
100
+ }
101
+ return { valid: true };
102
+ }
103
+
104
+ module.exports = {
105
+ NAMING_RULES,
106
+ WORKFLOW_STEPS,
107
+ DRAWING_CONSTRAINTS,
108
+ validateCanvasName,
109
+ validateStampName,
110
+ validateCanvasSize,
111
+ };