@pixel-normal-edit/mcp 2.0.8 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/command-bus.js +6 -3
- package/core/server.js +98 -3
- package/index.js +4 -0
- package/package.json +1 -1
- package/rules/README.md +476 -0
- package/rules/index.js +34 -0
- package/rules/prerequisites.js +202 -0
- package/rules/rules.js +152 -0
- package/rules/workflow.js +406 -0
- package/tools/{anchors.js → anchor-tools.js} +1 -1
- package/tools/{animation.js → animation-tools.js} +1 -1
- package/tools/{canvas.js → canvas-tools.js} +1 -1
- package/tools/{colors.js → color-tools.js} +1 -1
- package/tools/{drawing.js → drawing-tools.js} +1 -1
- package/tools/{filters.js → filter-tools.js} +1 -1
- package/tools/{health.js → health-tools.js} +1 -1
- package/tools/{history.js → history-tools.js} +1 -1
- package/tools/index.js +30 -14
- package/tools/{layer.js → layer-tools.js} +2 -2
- package/tools/{modes.js → mode-tools.js} +1 -1
- package/tools/{query.js → query-tools.js} +1 -1
- package/tools/{region.js → region-tools.js} +1 -1
- package/tools/{sprite.js → sprite-tools.js} +1 -1
- package/tools/{workspace.js → workspace-tools.js} +2 -3
package/core/command-bus.js
CHANGED
|
@@ -15,11 +15,14 @@ const TIMEOUT = parseInt(process.env.MCP_TIMEOUT || '20000');
|
|
|
15
15
|
/**
|
|
16
16
|
* Send a command payload to the browser via Firestore and wait for response.
|
|
17
17
|
* @param {Object} payload - The command action and parameters
|
|
18
|
+
* @param {number} timeoutOverride - Optional timeout in milliseconds
|
|
18
19
|
* @returns {Promise<Object>} MCP-compatible response object
|
|
19
20
|
*/
|
|
20
|
-
async function sendCommand(payload) {
|
|
21
|
+
async function sendCommand(payload, timeoutOverride = null) {
|
|
21
22
|
const id = crypto.randomUUID();
|
|
22
23
|
const ref = doc(db, 'mcp_sessions', SESSION, 'commands', id);
|
|
24
|
+
const actualTimeout = timeoutOverride || TIMEOUT;
|
|
25
|
+
|
|
23
26
|
await setDoc(ref, { ...payload, status: 'pending', timestamp: Date.now() });
|
|
24
27
|
|
|
25
28
|
return new Promise((resolve) => {
|
|
@@ -27,9 +30,9 @@ async function sendCommand(payload) {
|
|
|
27
30
|
unsub();
|
|
28
31
|
resolve({
|
|
29
32
|
isError: true,
|
|
30
|
-
content: [{ type: 'text', text: `⏱ Timeout (${
|
|
33
|
+
content: [{ type: 'text', text: `⏱ Timeout (${actualTimeout}ms). Is the browser tab open with session: ${SESSION}?` }]
|
|
31
34
|
});
|
|
32
|
-
},
|
|
35
|
+
}, actualTimeout);
|
|
33
36
|
|
|
34
37
|
const unsub = onSnapshot(ref, (snap) => {
|
|
35
38
|
const d = snap.data();
|
package/core/server.js
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
* Provides a tool registration factory for consistent tool definitions.
|
|
7
7
|
*/
|
|
8
8
|
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
9
|
-
const { sendCommand } = require('./command-bus');
|
|
9
|
+
const { sendCommand, SESSION } = require('./command-bus');
|
|
10
|
+
const workflow = require('../rules/workflow');
|
|
11
|
+
const { DRAWING_STEPS } = require('../rules/rules');
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Create a new MCP server instance
|
|
@@ -16,16 +18,109 @@ function createServer() {
|
|
|
16
18
|
return new McpServer({ name: 'PixelNormalEdit', version: '2.0.0' });
|
|
17
19
|
}
|
|
18
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Read-only tools that do not modify the canvas and should bypass strict workflow checks
|
|
23
|
+
*/
|
|
24
|
+
const READ_ONLY_TOOLS = [
|
|
25
|
+
'ping',
|
|
26
|
+
'layer_get_info',
|
|
27
|
+
'workspace_list_tabs',
|
|
28
|
+
'workspace_get_active_tab',
|
|
29
|
+
'animation_get_info',
|
|
30
|
+
'anchor_list',
|
|
31
|
+
'query_snapshot',
|
|
32
|
+
'query_bounding_box',
|
|
33
|
+
'query_palette',
|
|
34
|
+
'query_pixel',
|
|
35
|
+
'query_export_image',
|
|
36
|
+
'query_document_state',
|
|
37
|
+
'workflow_status',
|
|
38
|
+
'workflow_get_progress'
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Identify if a tool is a drawing tool that should only be allowed in drawing steps
|
|
43
|
+
*/
|
|
44
|
+
function isDrawingTool(name) {
|
|
45
|
+
return name.startsWith('draw_') ||
|
|
46
|
+
name.startsWith('bulk_') ||
|
|
47
|
+
name.startsWith('filter_') ||
|
|
48
|
+
name.startsWith('sprite_') ||
|
|
49
|
+
name.startsWith('region_') ||
|
|
50
|
+
name.startsWith('layer_') ||
|
|
51
|
+
name.startsWith('animation_') ||
|
|
52
|
+
name.startsWith('art_tree_');
|
|
53
|
+
}
|
|
54
|
+
|
|
19
55
|
/**
|
|
20
56
|
* Register a single-command tool on the server
|
|
21
57
|
* @param {McpServer} server - The MCP server instance
|
|
22
58
|
* @param {string} name - Tool name
|
|
23
59
|
* @param {string} desc - Tool description
|
|
24
60
|
* @param {Object} schema - Zod schema for parameters
|
|
25
|
-
* @param {Function} mapToCmd - Function mapping params to command payload
|
|
61
|
+
* @param {Function} mapToCmd - Function mapping params to command payload or returning MCP response
|
|
26
62
|
*/
|
|
27
63
|
function registerTool(server, name, desc, schema, mapToCmd) {
|
|
28
|
-
server.tool(name, desc, schema, async (params) =>
|
|
64
|
+
server.tool(name, desc, schema, async (params) => {
|
|
65
|
+
// 1. Strict Middleware Enforcement (Run BEFORE tool execution)
|
|
66
|
+
if (!READ_ONLY_TOOLS.includes(name)) {
|
|
67
|
+
const state = workflow.getState(SESSION);
|
|
68
|
+
|
|
69
|
+
// Allow workflow_start to run even if state is null
|
|
70
|
+
if (!state && name !== 'workflow_start') {
|
|
71
|
+
return {
|
|
72
|
+
isError: true,
|
|
73
|
+
content: [{ type: 'text', text: "⛔ Middleware Block: Workflow not started! Call workflow_start first." }]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (state) {
|
|
78
|
+
if (state.step_status === 'WAITING_FOR_USER') {
|
|
79
|
+
return {
|
|
80
|
+
isError: true,
|
|
81
|
+
content: [{ type: 'text', text: "⛔ Middleware Block: Workflow is paused! Waiting for user approval. You cannot execute this tool." }]
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (state.step_status === 'COMPLETED') {
|
|
86
|
+
return {
|
|
87
|
+
isError: true,
|
|
88
|
+
content: [{ type: 'text', text: "⛔ Middleware Block: Workflow is completed! Please start a new workflow." }]
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Block creating new tabs in EDIT_IMAGE mode
|
|
93
|
+
if (name === 'workspace_create_tab' && state.current_mode === 'EDIT_IMAGE') {
|
|
94
|
+
return {
|
|
95
|
+
isError: true,
|
|
96
|
+
content: [{ type: 'text', text: "⛔ Middleware Block: You cannot create new images in EDIT_IMAGE mode. Please only edit the existing image." }]
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Check Drawing Steps Enforcement
|
|
101
|
+
if (isDrawingTool(name)) {
|
|
102
|
+
const currentStep = state.steps[state.currentStepIndex];
|
|
103
|
+
if (!currentStep || !DRAWING_STEPS.includes(currentStep.id)) {
|
|
104
|
+
return {
|
|
105
|
+
isError: true,
|
|
106
|
+
content: [{ type: 'text', text: `⛔ Middleware Block: You cannot use drawing/layer tools in the current step ("${currentStep ? currentStep.label : 'None'}"). You must advance to a drawing step (e.g. EXECUTE_PHASES) first.` }]
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 2. Execute the tool implementation
|
|
114
|
+
const res = mapToCmd(params);
|
|
115
|
+
|
|
116
|
+
// 3. If the tool implementation returns an MCP response directly (local tool like workflow_*)
|
|
117
|
+
if (res && res.content) {
|
|
118
|
+
return res;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 4. Forward the command payload to the browser
|
|
122
|
+
return sendCommand(res);
|
|
123
|
+
});
|
|
29
124
|
}
|
|
30
125
|
|
|
31
126
|
module.exports = { createServer, registerTool, sendCommand };
|
package/index.js
CHANGED
|
@@ -28,6 +28,7 @@ require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') }
|
|
|
28
28
|
const { createServer } = require('./core/server');
|
|
29
29
|
const { registerAll: registerCoreTools } = require('./tools/index');
|
|
30
30
|
const { registerAll: registerArtTree } = require('./domains/art-tree/index');
|
|
31
|
+
const { registerAll: registerRules } = require('./rules/index');
|
|
31
32
|
|
|
32
33
|
// ── Initialize ────────────────────────────────────────────────────────────
|
|
33
34
|
const server = createServer();
|
|
@@ -35,6 +36,9 @@ const server = createServer();
|
|
|
35
36
|
// ── Register Core Tools ───────────────────────────────────────────────────
|
|
36
37
|
registerCoreTools(server);
|
|
37
38
|
|
|
39
|
+
// ── Register Rules / Workflow Tools (BẮT BUỘC: chạy trước khi vẽ) ────────
|
|
40
|
+
registerRules(server);
|
|
41
|
+
|
|
38
42
|
// ── Register Domain Modules ───────────────────────────────────────────────
|
|
39
43
|
registerArtTree(server);
|
|
40
44
|
// Future domains: registerPixelArt(server), registerCharacterDrawing(server), etc.
|
package/package.json
CHANGED
package/rules/README.md
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
# RULE: QUY TRÌNH TẠO, SỬA ẢNH VÀ TẠO ANIMATION
|
|
2
|
+
|
|
3
|
+
## 1. Nguyên tắc chung
|
|
4
|
+
|
|
5
|
+
Mọi thao tác vẽ, sửa ảnh hoặc tạo animation phải được thực hiện theo quy trình tuần tự, có trạng thái rõ ràng.
|
|
6
|
+
|
|
7
|
+
AI không được tự ý:
|
|
8
|
+
|
|
9
|
+
* Bỏ qua bước.
|
|
10
|
+
* Nhảy sang bước tiếp theo khi bước hiện tại chưa hoàn tất.
|
|
11
|
+
* Tự ý tạo ảnh mới trong quy trình sửa ảnh.
|
|
12
|
+
* Thay đổi các thành phần không nằm trong phạm vi yêu cầu.
|
|
13
|
+
* Ghi đè trạng thái của bước trước nếu chưa hoàn tất hoặc chưa được xác nhận.
|
|
14
|
+
|
|
15
|
+
Mỗi bước phải được lưu vào trạng thái, ví dụ:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
current_mode
|
|
19
|
+
current_step
|
|
20
|
+
current_layer
|
|
21
|
+
current_frame
|
|
22
|
+
user_approval_required
|
|
23
|
+
step_status
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Trạng thái mẫu:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
current_mode: CREATE_IMAGE
|
|
30
|
+
current_step: ANALYZE_REQUEST
|
|
31
|
+
current_layer: 0
|
|
32
|
+
current_frame: null
|
|
33
|
+
step_status: IN_PROGRESS
|
|
34
|
+
user_approval_required: false
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Các trạng thái có thể sử dụng:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
PENDING
|
|
41
|
+
IN_PROGRESS
|
|
42
|
+
WAITING_FOR_USER
|
|
43
|
+
COMPLETED
|
|
44
|
+
FAILED
|
|
45
|
+
CANCELLED
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
# 2. TẠO ẢNH MỚI
|
|
51
|
+
|
|
52
|
+
## Bước 1: Khởi tạo Canvas
|
|
53
|
+
|
|
54
|
+
Khi người dùng yêu cầu tạo ảnh:
|
|
55
|
+
|
|
56
|
+
1. Kiểm tra kích thước canvas.
|
|
57
|
+
2. Kích thước pixel bắt buộc phải do người dùng cung cấp.
|
|
58
|
+
3. Nếu người dùng chưa cung cấp kích thước, phải hỏi lại.
|
|
59
|
+
4. Không tự động sử dụng kích thước mặc định 32×32 nếu chưa được người dùng xác nhận.
|
|
60
|
+
|
|
61
|
+
Ví dụ:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
Canvas:
|
|
65
|
+
width: [user_input]
|
|
66
|
+
height: [user_input]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Sau khi nhận được kích thước, tạo canvas mới.
|
|
70
|
+
|
|
71
|
+
Trạng thái:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
current_step: INITIALIZE_CANVAS
|
|
75
|
+
step_status: COMPLETED
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Bước 2: Phân tích yêu cầu
|
|
81
|
+
|
|
82
|
+
Phân tích yêu cầu của người dùng thành các thành phần có cấu trúc.
|
|
83
|
+
|
|
84
|
+
Ví dụ:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
Subject:
|
|
88
|
+
- Cây
|
|
89
|
+
|
|
90
|
+
Components:
|
|
91
|
+
- Thân cây
|
|
92
|
+
- Cành cây
|
|
93
|
+
- Lá cây
|
|
94
|
+
- Hoa/quả
|
|
95
|
+
|
|
96
|
+
Environment:
|
|
97
|
+
- Mặt đất
|
|
98
|
+
- Bầu trời
|
|
99
|
+
- Vật thể xung quanh
|
|
100
|
+
|
|
101
|
+
Style:
|
|
102
|
+
- Pixel art
|
|
103
|
+
- Anime
|
|
104
|
+
- Realistic
|
|
105
|
+
- ...
|
|
106
|
+
|
|
107
|
+
Lighting:
|
|
108
|
+
- Direction
|
|
109
|
+
- Intensity
|
|
110
|
+
- Shadow
|
|
111
|
+
|
|
112
|
+
Composition:
|
|
113
|
+
- Position
|
|
114
|
+
- Scale
|
|
115
|
+
- Perspective
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Cấu trúc này phải có khả năng mở rộng tùy theo yêu cầu.
|
|
119
|
+
|
|
120
|
+
Trạng thái:
|
|
121
|
+
|
|
122
|
+
```text
|
|
123
|
+
current_step: ANALYZE_REQUEST
|
|
124
|
+
step_status: COMPLETED
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Bước 3: Lập kế hoạch vẽ
|
|
130
|
+
|
|
131
|
+
AI phải tạo kế hoạch vẽ theo thứ tự từ tổng thể đến chi tiết.
|
|
132
|
+
|
|
133
|
+
Ví dụ:
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
1. Phác thảo bố cục tổng thể.
|
|
137
|
+
2. Vẽ background.
|
|
138
|
+
3. Vẽ các hình khối chính.
|
|
139
|
+
4. Vẽ line hoặc silhouette.
|
|
140
|
+
5. Vẽ từng thành phần chính.
|
|
141
|
+
6. Thêm màu cơ bản.
|
|
142
|
+
7. Thêm ánh sáng và bóng.
|
|
143
|
+
8. Thêm chi tiết nhỏ.
|
|
144
|
+
9. Kiểm tra tổng thể.
|
|
145
|
+
10. Tinh chỉnh.
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
AI phải trả kế hoạch cho người dùng trước khi bắt đầu thực hiện.
|
|
149
|
+
|
|
150
|
+
Nếu quy trình yêu cầu xác nhận, chuyển sang:
|
|
151
|
+
|
|
152
|
+
```text
|
|
153
|
+
step_status: WAITING_FOR_USER
|
|
154
|
+
user_approval_required: true
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
AI chỉ được tiếp tục sau khi người dùng xác nhận.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
# 3. QUY TẮC VẼ THEO TỪNG GIAI ĐOẠN
|
|
162
|
+
|
|
163
|
+
AI phải vẽ theo từng giai đoạn, không thực hiện toàn bộ ảnh trong một bước duy nhất.
|
|
164
|
+
|
|
165
|
+
Thứ tự tổng quát:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
PHASE_0: SKETCH / BLOCKING
|
|
169
|
+
PHASE_1: BACKGROUND
|
|
170
|
+
PHASE_2: MAIN_SHAPES
|
|
171
|
+
PHASE_3: LINE / SILHOUETTE
|
|
172
|
+
PHASE_4: BASE_COLORS
|
|
173
|
+
PHASE_5: SHADING
|
|
174
|
+
PHASE_6: LIGHTING
|
|
175
|
+
PHASE_7: DETAILS
|
|
176
|
+
PHASE_8: FINAL_REVIEW
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Sau mỗi giai đoạn:
|
|
180
|
+
|
|
181
|
+
1. Lưu trạng thái.
|
|
182
|
+
2. Kiểm tra kết quả.
|
|
183
|
+
3. Nếu cần, cung cấp ảnh xem trước hoặc cho phép người dùng sử dụng lệnh xem ảnh.
|
|
184
|
+
4. Nếu chưa đạt, tiếp tục chỉnh sửa ở đúng giai đoạn hiện tại.
|
|
185
|
+
5. Không được chuyển sang giai đoạn tiếp theo nếu giai đoạn hiện tại chưa hoàn tất.
|
|
186
|
+
|
|
187
|
+
Ví dụ:
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
current_step: DRAW_BACKGROUND
|
|
191
|
+
step_status: IN_PROGRESS
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Sau khi hoàn tất:
|
|
195
|
+
|
|
196
|
+
```text
|
|
197
|
+
current_step: DRAW_BACKGROUND
|
|
198
|
+
step_status: COMPLETED
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Sau đó mới được chuyển sang:
|
|
202
|
+
|
|
203
|
+
```text
|
|
204
|
+
current_step: DRAW_MAIN_SHAPES
|
|
205
|
+
step_status: IN_PROGRESS
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
# 4. QUẢN LÝ LAYER
|
|
211
|
+
|
|
212
|
+
Layer được sử dụng xuyên suốt toàn bộ quy trình.
|
|
213
|
+
|
|
214
|
+
Cấu trúc cơ bản:
|
|
215
|
+
|
|
216
|
+
```text
|
|
217
|
+
Layer 0: Background
|
|
218
|
+
Layer 1: Main subject
|
|
219
|
+
Layer 2: Secondary subject
|
|
220
|
+
Layer 3: Details
|
|
221
|
+
Layer n: Additional elements
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Tuy nhiên, layer phải được phân chia theo thành phần cần chỉnh sửa độc lập.
|
|
225
|
+
|
|
226
|
+
Ví dụ với một cái cây:
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
Layer 0: Background
|
|
230
|
+
Layer 1: Trunk
|
|
231
|
+
Layer 2: Branches
|
|
232
|
+
Layer 3: Leaves
|
|
233
|
+
Layer 4: Fruits
|
|
234
|
+
Layer 5: Shadows
|
|
235
|
+
Layer 6: Highlights
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Nguyên tắc:
|
|
239
|
+
|
|
240
|
+
* Mỗi thành phần có thể chỉnh sửa độc lập nên được đặt trên layer riêng.
|
|
241
|
+
* Không gộp nhiều thành phần khác nhau vào cùng một layer nếu việc đó làm mất khả năng chỉnh sửa riêng.
|
|
242
|
+
* Khi thêm một thành phần mới, phải xác định layer phù hợp trước khi vẽ.
|
|
243
|
+
* Mọi thay đổi phải được ghi nhận vào trạng thái.
|
|
244
|
+
|
|
245
|
+
Ví dụ:
|
|
246
|
+
|
|
247
|
+
```text
|
|
248
|
+
current_layer: 3
|
|
249
|
+
layer_name: Leaves
|
|
250
|
+
layer_status: IN_PROGRESS
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
# 5. KIỂM TRA VÀ XÁC NHẬN
|
|
256
|
+
|
|
257
|
+
Sau mỗi giai đoạn, AI phải kiểm tra:
|
|
258
|
+
|
|
259
|
+
```text
|
|
260
|
+
- Đúng yêu cầu người dùng chưa?
|
|
261
|
+
- Bố cục có đúng không?
|
|
262
|
+
- Tỷ lệ có phù hợp không?
|
|
263
|
+
- Layer có đúng không?
|
|
264
|
+
- Thành phần có bị ảnh hưởng ngoài phạm vi không?
|
|
265
|
+
- Có lỗi phát sinh từ bước trước không?
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Nếu cần người dùng xác nhận:
|
|
269
|
+
|
|
270
|
+
```text
|
|
271
|
+
step_status: WAITING_FOR_USER
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
AI phải dừng và chờ phản hồi.
|
|
275
|
+
|
|
276
|
+
Người dùng có thể:
|
|
277
|
+
|
|
278
|
+
```text
|
|
279
|
+
APPROVE
|
|
280
|
+
CONTINUE
|
|
281
|
+
REVIEW
|
|
282
|
+
EDIT
|
|
283
|
+
UNDO
|
|
284
|
+
REGENERATE_CURRENT_STEP
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Nếu người dùng yêu cầu chỉnh sửa, chỉ chỉnh sửa bước hoặc layer liên quan, không tự động tạo lại toàn bộ ảnh.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
# 6. SỬA ẢNH
|
|
292
|
+
|
|
293
|
+
Quy trình sửa ảnh phải sử dụng ảnh hiện tại làm nguồn gốc.
|
|
294
|
+
|
|
295
|
+
AI không được tự ý tạo một ảnh mới thay thế ảnh hiện tại.
|
|
296
|
+
|
|
297
|
+
Quy trình:
|
|
298
|
+
|
|
299
|
+
```text
|
|
300
|
+
1. Nhận yêu cầu sửa.
|
|
301
|
+
2. Phân tích chính xác nội dung cần sửa.
|
|
302
|
+
3. Lấy ảnh hiện tại.
|
|
303
|
+
4. So sánh yêu cầu với ảnh hiện tại.
|
|
304
|
+
5. Xác định vùng hoặc layer cần chỉnh sửa.
|
|
305
|
+
6. Khoanh vùng khu vực cần sửa.
|
|
306
|
+
7. Thực hiện chỉnh sửa trong phạm vi đó.
|
|
307
|
+
8. Kiểm tra sự tương thích với môi trường xung quanh.
|
|
308
|
+
9. Điều chỉnh phần chuyển tiếp nếu cần.
|
|
309
|
+
10. Cập nhật thay đổi vào ảnh hiện tại.
|
|
310
|
+
11. Kiểm tra kết quả.
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Ví dụ:
|
|
314
|
+
|
|
315
|
+
```text
|
|
316
|
+
current_mode: EDIT_IMAGE
|
|
317
|
+
target_area: Layer 3 / Leaves
|
|
318
|
+
edit_scope: Specific region
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Nguyên tắc bắt buộc:
|
|
322
|
+
|
|
323
|
+
* Chỉ sửa phần được yêu cầu.
|
|
324
|
+
* Giữ nguyên các phần không liên quan.
|
|
325
|
+
* Không tạo lại toàn bộ ảnh.
|
|
326
|
+
* Không thay đổi bố cục, phong cách hoặc thành phần khác nếu người dùng không yêu cầu.
|
|
327
|
+
* Sau khi sửa phải kiểm tra sự hòa hợp với các vùng xung quanh.
|
|
328
|
+
|
|
329
|
+
Nếu chỉnh sửa chưa đạt:
|
|
330
|
+
|
|
331
|
+
```text
|
|
332
|
+
current_step: EDIT_TARGET_AREA
|
|
333
|
+
step_status: IN_PROGRESS
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Không được chuyển sang bước khác cho đến khi vùng chỉnh sửa hoàn tất.
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
# 7. TẠO ANIMATION MỚI
|
|
341
|
+
|
|
342
|
+
Quy trình tạo animation tương tự quy trình tạo ảnh nhưng bổ sung hệ thống frame.
|
|
343
|
+
|
|
344
|
+
## Bước 1: Khởi tạo
|
|
345
|
+
|
|
346
|
+
Xác định:
|
|
347
|
+
|
|
348
|
+
```text
|
|
349
|
+
Canvas:
|
|
350
|
+
width
|
|
351
|
+
height
|
|
352
|
+
|
|
353
|
+
Animation:
|
|
354
|
+
fps
|
|
355
|
+
total_frames
|
|
356
|
+
loop
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Nếu người dùng chưa cung cấp thông tin cần thiết, phải hỏi lại.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Bước 2: Phân tích animation
|
|
364
|
+
|
|
365
|
+
Phân tích:
|
|
366
|
+
|
|
367
|
+
```text
|
|
368
|
+
- Đối tượng.
|
|
369
|
+
- Chuyển động.
|
|
370
|
+
- Hướng chuyển động.
|
|
371
|
+
- Frame bắt đầu.
|
|
372
|
+
- Frame kết thúc.
|
|
373
|
+
- Các keyframe.
|
|
374
|
+
- Các frame trung gian.
|
|
375
|
+
- Layer cần sử dụng.
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Ví dụ:
|
|
379
|
+
|
|
380
|
+
```text
|
|
381
|
+
Frame 0: Initial pose
|
|
382
|
+
Frame 1: Movement begins
|
|
383
|
+
Frame 2: Mid movement
|
|
384
|
+
Frame 3: Peak movement
|
|
385
|
+
Frame 4: Return
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Bước 3: Tạo và xử lý từng frame
|
|
391
|
+
|
|
392
|
+
Mỗi frame phải được xử lý riêng theo đúng thứ tự:
|
|
393
|
+
|
|
394
|
+
```text
|
|
395
|
+
1. Activate frame.
|
|
396
|
+
2. Xác định trạng thái của frame.
|
|
397
|
+
3. Xác định layer cần vẽ.
|
|
398
|
+
4. Vẽ hoặc chỉnh sửa layer.
|
|
399
|
+
5. Kiểm tra tính liên tục với frame trước và sau.
|
|
400
|
+
6. Lưu frame.
|
|
401
|
+
7. Chuyển sang frame tiếp theo.
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Ví dụ:
|
|
405
|
+
|
|
406
|
+
```text
|
|
407
|
+
current_frame: 0
|
|
408
|
+
current_layer: 1
|
|
409
|
+
current_step: DRAW_FRAME
|
|
410
|
+
step_status: IN_PROGRESS
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Chỉ được chuyển sang:
|
|
414
|
+
|
|
415
|
+
```text
|
|
416
|
+
current_frame: 1
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
sau khi frame 0 đã hoàn tất.
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
# 8. KIỂM TRA TÍNH LIÊN TỤC CỦA ANIMATION
|
|
424
|
+
|
|
425
|
+
Sau khi hoàn thành các frame, phải kiểm tra:
|
|
426
|
+
|
|
427
|
+
```text
|
|
428
|
+
- Vị trí đối tượng có chuyển động liên tục không?
|
|
429
|
+
- Layer có nhất quán giữa các frame không?
|
|
430
|
+
- Có hiện tượng nhảy hình không?
|
|
431
|
+
- Có thay đổi ngoài ý muốn không?
|
|
432
|
+
- Bố cục có bị lệch không?
|
|
433
|
+
- Chuyển động có đúng yêu cầu không?
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Nếu phát hiện lỗi, chỉ quay lại frame hoặc layer bị lỗi để sửa.
|
|
437
|
+
|
|
438
|
+
Không được tạo lại toàn bộ animation nếu chỉ một frame hoặc một layer bị lỗi.
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
# 9. NGUYÊN TẮC TRẠNG THÁI BẮT BUỘC
|
|
443
|
+
|
|
444
|
+
Mọi thao tác phải tuân theo:
|
|
445
|
+
|
|
446
|
+
```text
|
|
447
|
+
CHECK_CURRENT_STATE
|
|
448
|
+
→ EXECUTE_CURRENT_STEP
|
|
449
|
+
→ SAVE_STATE
|
|
450
|
+
→ VALIDATE_RESULT
|
|
451
|
+
→ WAIT_FOR_USER_IF_REQUIRED
|
|
452
|
+
→ COMPLETE_CURRENT_STEP
|
|
453
|
+
→ MOVE_TO_NEXT_STEP
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Không được:
|
|
457
|
+
|
|
458
|
+
```text
|
|
459
|
+
CURRENT_STEP
|
|
460
|
+
→ SKIP
|
|
461
|
+
→ NEXT_STEP
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Mọi thao tác phải có trạng thái rõ ràng:
|
|
465
|
+
|
|
466
|
+
```text
|
|
467
|
+
mode
|
|
468
|
+
step
|
|
469
|
+
layer
|
|
470
|
+
frame
|
|
471
|
+
status
|
|
472
|
+
user_approval
|
|
473
|
+
history
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
Mục tiêu của hệ thống là đảm bảo toàn bộ quá trình tạo ảnh, sửa ảnh và tạo animation có thể kiểm soát, theo dõi, xem lại và tiếp tục chính xác từ bất kỳ bước nào mà không làm mất trạng thái trước đó.
|
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 and exports all rules, workflow engine, and prerequisite tools.
|
|
6
|
+
*
|
|
7
|
+
* This module provides:
|
|
8
|
+
* 1. rules.js — Defines rules (naming, constraints, validators)
|
|
9
|
+
* 2. workflow.js — Workflow engine (manages step order)
|
|
10
|
+
* 3. prerequisites.js — MCP Tools for workflow (start, status, advance, validate)
|
|
11
|
+
*
|
|
12
|
+
* How to add a new rule:
|
|
13
|
+
* - Add to rules.js (NAMING_RULES, WORKFLOW_STEPS, DRAWING_CONSTRAINTS)
|
|
14
|
+
* - If complex logic is needed, create a new file in rules/ and import it here
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const rules = require('./rules');
|
|
18
|
+
const workflow = require('./workflow');
|
|
19
|
+
const prerequisites = require('./prerequisites');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Register all workflow/prerequisite tools to the 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
|
+
};
|