vg-coder-cli 1.0.11 → 1.0.12
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/package.json +1 -1
- package/src/server/views/dashboard.html +274 -17
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
|
+
|
|
3
4
|
<head>
|
|
4
5
|
<meta charset="UTF-8">
|
|
5
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
border-radius: 12px;
|
|
29
30
|
padding: 30px;
|
|
30
31
|
margin-bottom: 30px;
|
|
31
|
-
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
|
|
32
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
.header h1 {
|
|
@@ -62,7 +63,7 @@
|
|
|
62
63
|
background: white;
|
|
63
64
|
border-radius: 12px;
|
|
64
65
|
padding: 25px;
|
|
65
|
-
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
|
|
66
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
|
66
67
|
transition: transform 0.3s ease;
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -84,9 +85,20 @@
|
|
|
84
85
|
font-size: 0.85em;
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
.method.get {
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
.method.get {
|
|
89
|
+
background: #3b82f6;
|
|
90
|
+
color: white;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.method.post {
|
|
94
|
+
background: #10b981;
|
|
95
|
+
color: white;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.method.delete {
|
|
99
|
+
background: #ef4444;
|
|
100
|
+
color: white;
|
|
101
|
+
}
|
|
90
102
|
|
|
91
103
|
.endpoint-path {
|
|
92
104
|
font-family: 'Courier New', monospace;
|
|
@@ -182,17 +194,92 @@
|
|
|
182
194
|
display: inline-block;
|
|
183
195
|
width: 16px;
|
|
184
196
|
height: 16px;
|
|
185
|
-
border: 3px solid rgba(255,255,255
|
|
197
|
+
border: 3px solid rgba(255, 255, 255, .3);
|
|
186
198
|
border-radius: 50%;
|
|
187
199
|
border-top-color: white;
|
|
188
200
|
animation: spin 1s ease-in-out infinite;
|
|
189
201
|
}
|
|
190
202
|
|
|
191
203
|
@keyframes spin {
|
|
192
|
-
to {
|
|
204
|
+
to {
|
|
205
|
+
transform: rotate(360deg);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.system-prompt-card {
|
|
210
|
+
background: white;
|
|
211
|
+
border-radius: 12px;
|
|
212
|
+
padding: 25px;
|
|
213
|
+
margin-bottom: 30px;
|
|
214
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.system-prompt-header {
|
|
218
|
+
display: flex;
|
|
219
|
+
justify-content: space-between;
|
|
220
|
+
align-items: center;
|
|
221
|
+
margin-bottom: 15px;
|
|
222
|
+
cursor: pointer;
|
|
223
|
+
user-select: none;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.system-prompt-header h2 {
|
|
227
|
+
color: #667eea;
|
|
228
|
+
font-size: 1.5em;
|
|
229
|
+
display: flex;
|
|
230
|
+
align-items: center;
|
|
231
|
+
gap: 10px;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.toggle-icon {
|
|
235
|
+
transition: transform 0.3s ease;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.toggle-icon.open {
|
|
239
|
+
transform: rotate(180deg);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.system-prompt-content {
|
|
243
|
+
max-height: 0;
|
|
244
|
+
overflow: hidden;
|
|
245
|
+
transition: max-height 0.3s ease;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.system-prompt-content.open {
|
|
249
|
+
max-height: 2000px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.prompt-text {
|
|
253
|
+
background: #f9fafb;
|
|
254
|
+
border: 2px solid #e5e7eb;
|
|
255
|
+
border-radius: 8px;
|
|
256
|
+
padding: 20px;
|
|
257
|
+
font-family: 'Courier New', monospace;
|
|
258
|
+
font-size: 0.9em;
|
|
259
|
+
line-height: 1.6;
|
|
260
|
+
white-space: pre-wrap;
|
|
261
|
+
max-height: 400px;
|
|
262
|
+
overflow-y: auto;
|
|
263
|
+
margin-bottom: 15px;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.btn-copy {
|
|
267
|
+
background: #10b981;
|
|
268
|
+
display: inline-flex;
|
|
269
|
+
align-items: center;
|
|
270
|
+
gap: 8px;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.btn-copy:hover {
|
|
274
|
+
background: #059669;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.btn-copy.copied {
|
|
278
|
+
background: #6366f1;
|
|
193
279
|
}
|
|
194
280
|
</style>
|
|
195
281
|
</head>
|
|
282
|
+
|
|
196
283
|
<body>
|
|
197
284
|
<div class="container">
|
|
198
285
|
<div class="header">
|
|
@@ -201,6 +288,24 @@
|
|
|
201
288
|
<span class="status" id="status">● Server Running</span>
|
|
202
289
|
</div>
|
|
203
290
|
|
|
291
|
+
<!-- System Prompt Section -->
|
|
292
|
+
<div class="system-prompt-card">
|
|
293
|
+
<div class="system-prompt-header" onclick="toggleSystemPrompt()">
|
|
294
|
+
<h2>
|
|
295
|
+
<span>📝</span>
|
|
296
|
+
<span>AI System Prompt</span>
|
|
297
|
+
</h2>
|
|
298
|
+
<span class="toggle-icon" id="toggle-icon">▼</span>
|
|
299
|
+
</div>
|
|
300
|
+
<div class="system-prompt-content" id="system-prompt-content">
|
|
301
|
+
<div class="prompt-text" id="prompt-text"></div>
|
|
302
|
+
<button class="btn btn-copy" onclick="copySystemPrompt()">
|
|
303
|
+
<span id="copy-icon">📋</span>
|
|
304
|
+
<span id="copy-text">Copy System Prompt</span>
|
|
305
|
+
</button>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
|
|
204
309
|
<div class="endpoints">
|
|
205
310
|
<!-- Health Check -->
|
|
206
311
|
<div class="endpoint-card">
|
|
@@ -315,14 +420,14 @@
|
|
|
315
420
|
const btn = event.target;
|
|
316
421
|
const path = document.getElementById('analyze-path').value;
|
|
317
422
|
const maxTokens = document.getElementById('analyze-tokens').value;
|
|
318
|
-
|
|
423
|
+
|
|
319
424
|
showLoading(btn);
|
|
320
425
|
try {
|
|
321
426
|
const res = await fetch(`${API_BASE}/api/analyze`, {
|
|
322
427
|
method: 'POST',
|
|
323
428
|
headers: { 'Content-Type': 'application/json' },
|
|
324
|
-
body: JSON.stringify({
|
|
325
|
-
path,
|
|
429
|
+
body: JSON.stringify({
|
|
430
|
+
path,
|
|
326
431
|
options: { maxTokens: parseInt(maxTokens) }
|
|
327
432
|
})
|
|
328
433
|
});
|
|
@@ -348,7 +453,7 @@
|
|
|
348
453
|
async function testInfo() {
|
|
349
454
|
const btn = event.target;
|
|
350
455
|
const path = document.getElementById('info-path').value;
|
|
351
|
-
|
|
456
|
+
|
|
352
457
|
showLoading(btn);
|
|
353
458
|
try {
|
|
354
459
|
const res = await fetch(`${API_BASE}/api/info?path=${encodeURIComponent(path)}`);
|
|
@@ -363,7 +468,7 @@
|
|
|
363
468
|
async function testExecute() {
|
|
364
469
|
const btn = event.target;
|
|
365
470
|
const bash = document.getElementById('execute-bash').value;
|
|
366
|
-
|
|
471
|
+
|
|
367
472
|
if (!bash.trim()) {
|
|
368
473
|
showResponse('execute-response', { error: 'Bash script is required' }, true);
|
|
369
474
|
return;
|
|
@@ -387,7 +492,7 @@
|
|
|
387
492
|
async function testClean() {
|
|
388
493
|
const btn = event.target;
|
|
389
494
|
const output = document.getElementById('clean-output').value;
|
|
390
|
-
|
|
495
|
+
|
|
391
496
|
showLoading(btn);
|
|
392
497
|
try {
|
|
393
498
|
const res = await fetch(`${API_BASE}/api/clean`, {
|
|
@@ -403,19 +508,171 @@
|
|
|
403
508
|
resetButton(btn, 'Clean Directory');
|
|
404
509
|
}
|
|
405
510
|
|
|
406
|
-
//
|
|
407
|
-
|
|
511
|
+
// System Prompt
|
|
512
|
+
const SYSTEM_PROMPT = `# VG Coder AI System Prompt
|
|
513
|
+
|
|
514
|
+
## Command Prefixes
|
|
515
|
+
|
|
516
|
+
### /ask - Question & Answer Mode
|
|
517
|
+
Khi người dùng hỏi với prefix /ask, họ đang muốn tìm hiểu hoặc được giải thích về một vấn đề.
|
|
518
|
+
|
|
519
|
+
**Response Format:** Markdown
|
|
520
|
+
- Trả lời chi tiết, rõ ràng
|
|
521
|
+
- Sử dụng code blocks, lists, tables khi cần
|
|
522
|
+
- Cung cấp ví dụ minh họa
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
### /plan - Planning Mode
|
|
527
|
+
Khi người dùng muốn lên kế hoạch với prefix /plan, tạo một implementation plan chi tiết.
|
|
528
|
+
|
|
529
|
+
**Response Format:** Markdown checklist với bash commands
|
|
530
|
+
- Chia nhỏ thành các bước cụ thể
|
|
531
|
+
- Mỗi bước có bash command tương ứng
|
|
532
|
+
- Sắp xếp theo thứ tự logic
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
### /fix - Bug Fix Mode
|
|
537
|
+
Khi người dùng cần fix bug với prefix /fix, phân tích lỗi và đưa ra giải pháp.
|
|
538
|
+
|
|
539
|
+
**Response Format:** Markdown + Bash script
|
|
540
|
+
1. **Phân tích lỗi:** Giải thích nguyên nhân
|
|
541
|
+
2. **Giải pháp:** Mô tả cách fix
|
|
542
|
+
3. **Bash script:** Code để fix (nếu cần)
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
### /code - Code Generation Mode
|
|
547
|
+
Khi người dùng hỏi với prefix /code, trả về **BASH SCRIPT DUY NHẤT** để tạo/cập nhật files.
|
|
548
|
+
|
|
549
|
+
## ⚠️ QUY TẮC BẮT BUỘC
|
|
550
|
+
|
|
551
|
+
### 1. Chỉ bao gồm files có thay đổi
|
|
552
|
+
- ❌ **KHÔNG** bao gồm files không có sự thay đổi nội dung
|
|
553
|
+
- ✅ Nếu nội dung file sau chỉnh sửa giống 100% bản cũ → **BỎ QUA**
|
|
554
|
+
|
|
555
|
+
### 2. Format Script Chuẩn
|
|
556
|
+
|
|
557
|
+
**Mỗi file PHẢI theo cú pháp:**
|
|
558
|
+
\`\`\`bash
|
|
559
|
+
mkdir -p $(dirname "path/to/file.ext")
|
|
560
|
+
cat <<'EOF' > path/to/file.ext
|
|
561
|
+
... toàn bộ nội dung file sau khi chỉnh sửa ...
|
|
562
|
+
EOF
|
|
563
|
+
\`\`\`
|
|
564
|
+
|
|
565
|
+
### 3. Chi tiết quan trọng
|
|
566
|
+
- ✅ **LUÔN** có \`mkdir -p $(dirname "...")\` trước mỗi file
|
|
567
|
+
- ✅ Sử dụng \`<<'EOF'\` (có dấu nháy đơn) để tránh bash expansion
|
|
568
|
+
- ✅ Ghi đè hoàn toàn file bằng nội dung mới
|
|
569
|
+
- ✅ Tự động tạo file và thư mục cha nếu chưa tồn tại
|
|
570
|
+
- ✅ Đường dẫn giống với file mẫu đính kèm
|
|
571
|
+
|
|
572
|
+
### 4. Example Output
|
|
573
|
+
|
|
574
|
+
\`\`\`bash
|
|
575
|
+
# Create/Update component file
|
|
576
|
+
mkdir -p $(dirname "src/components/Button/index.tsx")
|
|
577
|
+
cat <<'EOF' > src/components/Button/index.tsx
|
|
578
|
+
import React from 'react';
|
|
579
|
+
|
|
580
|
+
export const Button = () => {
|
|
581
|
+
return <button>Click me</button>;
|
|
582
|
+
};
|
|
583
|
+
EOF
|
|
584
|
+
|
|
585
|
+
# Create/Update styles
|
|
586
|
+
mkdir -p $(dirname "src/components/Button/styles.css")
|
|
587
|
+
cat <<'EOF' > src/components/Button/styles.css
|
|
588
|
+
.button {
|
|
589
|
+
padding: 10px 20px;
|
|
590
|
+
background: blue;
|
|
591
|
+
}
|
|
592
|
+
EOF
|
|
593
|
+
\`\`\`
|
|
594
|
+
|
|
595
|
+
---
|
|
596
|
+
|
|
597
|
+
## Integration với VG Coder CLI
|
|
598
|
+
|
|
599
|
+
Bash scripts được generate sẽ được thực thi qua:
|
|
600
|
+
\`\`\`bash
|
|
601
|
+
POST http://localhost:6868/api/execute
|
|
602
|
+
{
|
|
603
|
+
"bash": "mkdir -p $(dirname \\"src/...\\")\\\\ncat <<'EOF' > ..."
|
|
604
|
+
}
|
|
605
|
+
\`\`\`
|
|
606
|
+
|
|
607
|
+
API sẽ:
|
|
608
|
+
1. ✅ Validate bash syntax trong \`.vg/temp-execute\`
|
|
609
|
+
2. ✅ Execute tại working directory nếu syntax OK
|
|
610
|
+
3. ✅ Trả về stdout/stderr/exitCode
|
|
611
|
+
4. ✅ Auto cleanup temp directory
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## Best Practices
|
|
616
|
+
|
|
617
|
+
### DO ✅
|
|
618
|
+
- Luôn dùng \`mkdir -p $(dirname "...")\` trước mỗi file
|
|
619
|
+
- Sử dụng \`<<'EOF'\` để tránh variable expansion
|
|
620
|
+
- Ghi đè toàn bộ nội dung file
|
|
621
|
+
- Chỉ include files có thay đổi thực sự
|
|
622
|
+
|
|
623
|
+
### DON'T ❌
|
|
624
|
+
- Không tạo file mà không tạo thư mục cha
|
|
625
|
+
- Không dùng \`<<EOF\` (thiếu quotes) nếu có \`$\` trong content
|
|
626
|
+
- Không include files không thay đổi
|
|
627
|
+
- Không dùng relative paths phức tạp`;
|
|
628
|
+
|
|
629
|
+
// Load system prompt on page load
|
|
630
|
+
document.getElementById('prompt-text').textContent = SYSTEM_PROMPT;
|
|
631
|
+
|
|
632
|
+
function toggleSystemPrompt() {
|
|
633
|
+
const content = document.getElementById('system-prompt-content');
|
|
634
|
+
const icon = document.getElementById('toggle-icon');
|
|
635
|
+
content.classList.toggle('open');
|
|
636
|
+
icon.classList.toggle('open');
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function copySystemPrompt() {
|
|
640
|
+
const copyBtn = event.target.closest('.btn-copy');
|
|
641
|
+
const copyIcon = document.getElementById('copy-icon');
|
|
642
|
+
const copyText = document.getElementById('copy-text');
|
|
643
|
+
|
|
644
|
+
navigator.clipboard.writeText(SYSTEM_PROMPT).then(() => {
|
|
645
|
+
copyBtn.classList.add('copied');
|
|
646
|
+
copyIcon.textContent = '✓';
|
|
647
|
+
copyText.textContent = 'Copied!';
|
|
648
|
+
|
|
649
|
+
setTimeout(() => {
|
|
650
|
+
copyBtn.classList.remove('copied');
|
|
651
|
+
copyIcon.textContent = '📋';
|
|
652
|
+
copyText.textContent = 'Copy System Prompt';
|
|
653
|
+
}, 2000);
|
|
654
|
+
}).catch(err => {
|
|
655
|
+
alert('Failed to copy: ' + err.message);
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Check server status ONCE on page load
|
|
660
|
+
(async () => {
|
|
408
661
|
try {
|
|
409
662
|
const res = await fetch(`${API_BASE}/health`);
|
|
410
663
|
if (res.ok) {
|
|
664
|
+
const data = await res.json();
|
|
411
665
|
document.getElementById('status').textContent = '● Server Running';
|
|
412
666
|
document.getElementById('status').style.background = '#10b981';
|
|
667
|
+
// Auto-show health check result
|
|
668
|
+
showResponse('health-response', data);
|
|
413
669
|
}
|
|
414
670
|
} catch {
|
|
415
671
|
document.getElementById('status').textContent = '● Server Offline';
|
|
416
672
|
document.getElementById('status').style.background = '#ef4444';
|
|
417
673
|
}
|
|
418
|
-
}
|
|
674
|
+
})();
|
|
419
675
|
</script>
|
|
420
676
|
</body>
|
|
421
|
-
|
|
677
|
+
|
|
678
|
+
</html>
|