vg-coder-cli 2.0.30 → 2.0.32

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 (40) hide show
  1. package/ARCHITECTURE.md +255 -0
  2. package/README.md +0 -11
  3. package/change.sh +0 -0
  4. package/dist/vg-coder-bundle.js +42 -0
  5. package/gulpfile.js +111 -0
  6. package/package.json +19 -11
  7. package/scripts/postinstall.js +13 -3
  8. package/src/index.js +28 -220
  9. package/src/server/api-server.js +120 -428
  10. package/src/server/views/css/bubble.css +81 -0
  11. package/src/server/views/css/code-viewer.css +58 -0
  12. package/src/server/views/css/terminal.css +59 -155
  13. package/src/server/views/dashboard.css +78 -678
  14. package/src/server/views/dashboard.html +39 -278
  15. package/src/server/views/js/api.js +2 -22
  16. package/src/server/views/js/config.js +27 -15
  17. package/src/server/views/js/event-protocol.js +263 -0
  18. package/src/server/views/js/features/bubble-features/index.js +125 -0
  19. package/src/server/views/js/features/bubble-features/paste-run-feature.js +16 -0
  20. package/src/server/views/js/features/bubble-features/terminal-feature.js +16 -0
  21. package/src/server/views/js/features/bubble.js +175 -0
  22. package/src/server/views/js/features/code-viewer.js +90 -0
  23. package/src/server/views/js/features/commands.js +34 -81
  24. package/src/server/views/js/features/editor-tabs.js +19 -46
  25. package/src/server/views/js/features/git-view.js +63 -81
  26. package/src/server/views/js/features/iframe-manager.js +3 -97
  27. package/src/server/views/js/features/monaco-manager.js +19 -39
  28. package/src/server/views/js/features/project-switcher.js +7 -63
  29. package/src/server/views/js/features/resize.js +5 -16
  30. package/src/server/views/js/features/structure.js +38 -106
  31. package/src/server/views/js/features/terminal.js +102 -418
  32. package/src/server/views/js/handlers.js +60 -43
  33. package/src/server/views/js/main.js +75 -179
  34. package/src/server/views/js/shadow-entry.js +21 -0
  35. package/src/server/views/js/utils.js +48 -28
  36. package/src/server/views/vg-coder/_metadata/generated_indexed_rulesets/_ruleset1 +0 -0
  37. package/src/server/views/vg-coder/controller.js +33 -258
  38. package/vetgo-auto/chrome/src/utils/injector-script.ts +33 -258
  39. package/vetgo-auto/vg-coder.zip +0 -0
  40. package/src/server/views/dashboard.js +0 -457
@@ -1,457 +0,0 @@
1
- const API_BASE = window.location.origin;
2
- let lastAnalyzeResult = null;
3
-
4
- // System Prompt
5
- const SYSTEM_PROMPT = `# VG Coder AI System Prompt
6
-
7
- ## Command Prefixes
8
-
9
- ### /ask - Question & Answer Mode
10
- 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 đề.
11
-
12
- **Response Format:** Markdown
13
- - Trả lời chi tiết, rõ ràng
14
- - Sử dụng code blocks, lists, tables khi cần
15
- - Cung cấp ví dụ minh họa
16
-
17
- ---
18
-
19
- ### /plan - Planning Mode
20
- 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.
21
-
22
- **Response Format:** Markdown checklist với bash commands
23
- - Chia nhỏ thành các bước cụ thể
24
- - Mỗi bước có bash command tương ứng
25
- - Sắp xếp theo thứ tự logic
26
-
27
- ---
28
-
29
- ### /fix - Bug Fix Mode
30
- 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.
31
-
32
- **Response Format:** Markdown + Bash script
33
- 1. **Phân tích lỗi:** Giải thích nguyên nhân
34
- 2. **Giải pháp:** Mô tả cách fix
35
- 3. **Bash script:** Code để fix (nếu cần)
36
-
37
- ---
38
-
39
- ### /code - Code Generation Mode
40
- 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.
41
-
42
- ## ⚠️ QUY TẮC BẮT BUỘC
43
-
44
- ### 1. Chỉ bao gồm files có thay đổi
45
- - ❌ **KHÔNG** bao gồm files không có sự thay đổi nội dung
46
- - ✅ Nếu nội dung file sau chỉnh sửa giống 100% bản cũ → **BỎ QUA**
47
-
48
- ### 2. Format Script Chuẩn
49
-
50
- **Mỗi file PHẢI theo cú pháp:**
51
- \\\`\\\`\\\`bash
52
- mkdir -p $(dirname "path/to/file.ext")
53
- cat <<'EOF' > path/to/file.ext
54
- ... toàn bộ nội dung file sau khi chỉnh sửa ...
55
- EOF
56
- \\\`\\\`\\\`
57
-
58
- ### 3. Chi tiết quan trọng
59
- - ✅ **LUÔN** có \\\`mkdir -p $(dirname "...")\\\` trước mỗi file
60
- - ✅ Sử dụng \\\`<<'EOF'\\\` (có dấu nháy đơn) để tránh bash expansion
61
- - ✅ Ghi đè hoàn toàn file bằng nội dung mới
62
- - ✅ Tự động tạo file và thư mục cha nếu chưa tồn tại
63
- - ✅ Đường dẫn giống với file mẫu đính kèm
64
-
65
- ### 4. Example Output
66
-
67
- \\\`\\\`\\\`bash
68
- # Create/Update component file
69
- mkdir -p $(dirname "src/components/Button/index.tsx")
70
- cat <<'EOF' > src/components/Button/index.tsx
71
- import React from 'react';
72
-
73
- export const Button = () => {
74
- return <button>Click me</button>;
75
- };
76
- EOF
77
-
78
- # Create/Update styles
79
- mkdir -p $(dirname "src/components/Button/styles.css")
80
- cat <<'EOF' > src/components/Button/styles.css
81
- .button {
82
- padding: 10px 20px;
83
- background: blue;
84
- }
85
- EOF
86
- \\\`\\\`\\\`
87
-
88
- ---
89
-
90
- ## Integration với VG Coder CLI
91
-
92
- Bash scripts được generate sẽ được thực thi qua:
93
- \\\`\\\`\\\`bash
94
- POST http://localhost:6868/api/execute
95
- {
96
- "bash": "mkdir -p $(dirname \\\\"src/...\\\\")\\\\\\\ncat <<'EOF' > ..."
97
- }
98
- \\\`\\\`\\\`
99
-
100
- API sẽ:
101
- 1. ✅ Validate bash syntax trong \\\`.vg/temp-execute\\\`
102
- 2. ✅ Execute tại working directory nếu syntax OK
103
- 3. ✅ Trả về stdout/stderr/exitCode
104
- 4. ✅ Auto cleanup temp directory
105
-
106
- ---
107
-
108
- ## Best Practices
109
-
110
- ### DO ✅
111
- - Luôn dùng \\\`mkdir -p $(dirname "...")\\\` trước mỗi file
112
- - Sử dụng \\\`<<'EOF'\\\` để tránh variable expansion
113
- - Ghi đè toàn bộ nội dung file
114
- - Chỉ include files có thay đổi thực sự
115
-
116
- ### DON'T ❌
117
- - Không tạo file mà không tạo thư mục cha
118
- - Không dùng \\\`<<EOF\\\` (thiếu quotes) nếu có \\\`$\\\` trong content
119
- - Không include files không thay đổi
120
- - Không dùng relative paths phức tạp`;
121
-
122
- // Load system prompt on page load
123
- document.addEventListener('DOMContentLoaded', () => {
124
- document.getElementById('prompt-text').textContent = SYSTEM_PROMPT;
125
- checkServerStatus();
126
- });
127
-
128
- function toggleSystemPrompt() {
129
- const content = document.getElementById('system-prompt-content');
130
- const icon = document.getElementById('toggle-icon');
131
- content.classList.toggle('open');
132
- icon.classList.toggle('open');
133
- }
134
-
135
- function copySystemPrompt() {
136
- const copyBtn = event.target.closest('.btn-copy');
137
- const copyIcon = document.getElementById('copy-icon');
138
- const copyText = document.getElementById('copy-text');
139
-
140
- navigator.clipboard.writeText(SYSTEM_PROMPT).then(() => {
141
- copyBtn.classList.add('copied');
142
- copyIcon.textContent = '✓';
143
- copyText.textContent = 'Copied';
144
- showToast('Đã copy System Prompt', 'success');
145
-
146
- setTimeout(() => {
147
- copyBtn.classList.remove('copied');
148
- copyIcon.textContent = '📋';
149
- copyText.textContent = 'Copy System Prompt';
150
- }, 2000);
151
- }).catch(err => {
152
- showToast('Lỗi copy: ' + err.message, 'error');
153
- });
154
- }
155
-
156
- function showResponse(elementId, data, isError = false) {
157
- const el = document.getElementById(elementId);
158
- el.className = 'response show ' + (isError ? 'error' : 'success');
159
- el.innerHTML = '<pre>' + JSON.stringify(data, null, 2) + '</pre>';
160
- }
161
-
162
- function showLoading(button, originalText) {
163
- button.disabled = true;
164
- button.innerHTML = '<span class="loading"></span>';
165
- button.dataset.originalText = originalText;
166
- }
167
-
168
- function resetButton(button) {
169
- button.disabled = false;
170
- const originalText = button.dataset.originalText;
171
- button.innerHTML = originalText;
172
- }
173
-
174
- async function testAnalyze() {
175
- const btn = event.target.closest('.btn');
176
- const path = document.getElementById('analyze-path').value;
177
-
178
- showLoading(btn, btn.innerHTML);
179
- try {
180
- const res = await fetch(`${API_BASE}/api/analyze`, {
181
- method: 'POST',
182
- headers: { 'Content-Type': 'application/json' },
183
- body: JSON.stringify({ path })
184
- });
185
-
186
- if (res.ok) {
187
- const text = await res.text();
188
- lastAnalyzeResult = text;
189
-
190
- // Download file
191
- const blob = new Blob([text], { type: 'text/plain' });
192
- const url = window.URL.createObjectURL(blob);
193
- const a = document.createElement('a');
194
- a.href = url;
195
- a.download = 'project.txt';
196
- a.click();
197
-
198
- showResponse('analyze-response', {
199
- success: true,
200
- message: 'File downloaded!',
201
- files: text.split('\n').filter(l => l.includes('===== FILE:')).length,
202
- size: (text.length / 1024).toFixed(2) + ' KB'
203
- });
204
- showToast('Đã download file', 'success');
205
- } else {
206
- const data = await res.json();
207
- showResponse('analyze-response', data, true);
208
- showToast('Lỗi analyze', 'error');
209
- }
210
- } catch (err) {
211
- showResponse('analyze-response', { error: err.message }, true);
212
- showToast('Lỗi: ' + err.message, 'error');
213
- }
214
- resetButton(btn);
215
- }
216
-
217
- async function copyAnalyzeResult() {
218
- const copyBtn = event.target.closest('.btn-copy');
219
- const copyIcon = document.getElementById('analyze-copy-icon');
220
- const copyText = document.getElementById('analyze-copy-text');
221
-
222
- if (!lastAnalyzeResult) {
223
- // Fetch if not already analyzed
224
- const path = document.getElementById('analyze-path').value;
225
- showLoading(copyBtn, copyBtn.innerHTML);
226
-
227
- try {
228
- const res = await fetch(`${API_BASE}/api/analyze`, {
229
- method: 'POST',
230
- headers: { 'Content-Type': 'application/json' },
231
- body: JSON.stringify({ path })
232
- });
233
-
234
- if (res.ok) {
235
- lastAnalyzeResult = await res.text();
236
- } else {
237
- showToast('Lỗi analyze', 'error');
238
- resetButton(copyBtn);
239
- return;
240
- }
241
- } catch (err) {
242
- showToast('Lỗi: ' + err.message, 'error');
243
- resetButton(copyBtn);
244
- return;
245
- }
246
- resetButton(copyBtn);
247
- }
248
-
249
- // Copy to clipboard using ClipboardItem
250
- try {
251
- const blob = new Blob([lastAnalyzeResult], { type: 'text/plain' });
252
- const item = new ClipboardItem({ 'text/plain': blob });
253
- await navigator.clipboard.write([item]);
254
-
255
- copyBtn.classList.add('copied');
256
- copyIcon.textContent = '✓';
257
- copyText.textContent = 'Copied';
258
- showToast('Đã copy project.txt', 'success');
259
-
260
- setTimeout(() => {
261
- copyBtn.classList.remove('copied');
262
- copyIcon.textContent = '📋';
263
- copyText.textContent = 'Copy Text';
264
- }, 2000);
265
- } catch (err) {
266
- try {
267
- await navigator.clipboard.writeText(lastAnalyzeResult);
268
- copyBtn.classList.add('copied');
269
- copyIcon.textContent = '✓';
270
- copyText.textContent = 'Copied';
271
- showToast('Đã copy project.txt', 'success');
272
-
273
- setTimeout(() => {
274
- copyBtn.classList.remove('copied');
275
- copyIcon.textContent = '📋';
276
- copyText.textContent = 'Copy Text';
277
- }, 2000);
278
- } catch (fallbackErr) {
279
- showToast('Lỗi copy: ' + fallbackErr.message, 'error');
280
- }
281
- }
282
- }
283
-
284
- async function copyAsFile(filename, content) {
285
- const blob = new Blob([content], {
286
- type: "application/octet-stream"
287
- });
288
-
289
- const item = new ClipboardItem(
290
- { [blob.type]: blob },
291
- {
292
- type: "application/octet-stream",
293
- presentationStyle: "attachment",
294
- name: filename
295
- }
296
- );
297
-
298
- await navigator.clipboard.write([item]);
299
- }
300
-
301
- async function copyAnalyzeAsFile() {
302
- const copyBtn = event.target.closest('.btn-copy');
303
- const copyIcon = document.getElementById('analyze-file-icon');
304
- const copyText = document.getElementById('analyze-file-text');
305
-
306
- if (!lastAnalyzeResult) {
307
- // Fetch if not already analyzed
308
- const path = document.getElementById('analyze-path').value;
309
- showLoading(copyBtn, copyBtn.innerHTML);
310
-
311
- try {
312
- const res = await fetch(`${API_BASE}/api/analyze`, {
313
- method: 'POST',
314
- headers: { 'Content-Type': 'application/json' },
315
- body: JSON.stringify({ path })
316
- });
317
-
318
- if (res.ok) {
319
- lastAnalyzeResult = await res.text();
320
- } else {
321
- showToast('Lỗi analyze', 'error');
322
- resetButton(copyBtn);
323
- return;
324
- }
325
- } catch (err) {
326
- showToast('Lỗi: ' + err.message, 'error');
327
- resetButton(copyBtn);
328
- return;
329
- }
330
- resetButton(copyBtn);
331
- }
332
-
333
- try {
334
- await copyAsFile("project.txt", lastAnalyzeResult);
335
-
336
- copyBtn.classList.add('copied');
337
- copyIcon.textContent = '✓';
338
- copyText.textContent = 'Copied';
339
- showToast('Đã copy file', 'success');
340
-
341
- setTimeout(() => {
342
- copyBtn.classList.remove('copied');
343
- copyIcon.textContent = '📄';
344
- copyText.textContent = 'Copy as File';
345
- }, 2000);
346
- } catch (err) {
347
- showToast('Lỗi copy: ' + err.message, 'error');
348
- }
349
- }
350
-
351
- async function testExecute() {
352
- const btn = event.target.closest('.btn');
353
- const bash = document.getElementById('execute-bash').value;
354
-
355
- if (!bash.trim()) {
356
- showToast('Vui lòng nhập bash script', 'error');
357
- return;
358
- }
359
-
360
- showLoading(btn, btn.innerHTML);
361
- try {
362
- const res = await fetch(`${API_BASE}/api/execute`, {
363
- method: 'POST',
364
- headers: { 'Content-Type': 'application/json' },
365
- body: JSON.stringify({ bash })
366
- });
367
- const data = await res.json();
368
- showResponse('execute-response', data, !res.ok || !data.success);
369
-
370
- if (data.success) {
371
- showToast('Thực thi thành công', 'success');
372
- } else {
373
- showToast('Thực thi thất bại', 'error');
374
- }
375
- } catch (err) {
376
- showResponse('execute-response', { error: err.message }, true);
377
- showToast('Lỗi: ' + err.message, 'error');
378
- }
379
- resetButton(btn);
380
- }
381
-
382
- async function executeFromClipboard() {
383
- const btn = event.target.closest('.btn');
384
-
385
- showLoading(btn, btn.innerHTML);
386
-
387
- try {
388
- const clipboardText = await navigator.clipboard.readText();
389
-
390
- if (!clipboardText || !clipboardText.trim()) {
391
- showToast('Clipboard trống!', 'error');
392
- showResponse('execute-response', {
393
- error: 'Clipboard is empty',
394
- message: 'Please copy a bash script to clipboard first'
395
- }, true);
396
- resetButton(btn);
397
- return;
398
- }
399
-
400
- document.getElementById('execute-bash').value = clipboardText;
401
-
402
- const res = await fetch(`${API_BASE}/api/execute`, {
403
- method: 'POST',
404
- headers: { 'Content-Type': 'application/json' },
405
- body: JSON.stringify({ bash: clipboardText })
406
- });
407
- const data = await res.json();
408
- showResponse('execute-response', data, !res.ok || !data.success);
409
-
410
- if (data.success) {
411
- showToast('Thực thi từ clipboard OK', 'success');
412
- } else {
413
- if (data.syntaxError) {
414
- showToast('Lỗi syntax script', 'error');
415
- } else {
416
- showToast('Thực thi thất bại', 'error');
417
- }
418
- }
419
- } catch (err) {
420
- if (err.name === 'NotAllowedError') {
421
- showToast('Không có quyền clipboard', 'error');
422
- } else {
423
- showResponse('execute-response', { error: err.message }, true);
424
- showToast('Lỗi: ' + err.message, 'error');
425
- }
426
- }
427
- resetButton(btn);
428
- }
429
-
430
- function showToast(message, type = 'success') {
431
- const toast = document.getElementById('toast');
432
- // Reset text content to remove potential icon junk
433
- toast.textContent = message;
434
- toast.className = `toast ${type}`;
435
- toast.classList.add('show');
436
-
437
- // Clear previous timeout if exists
438
- if (toast.timeoutId) clearTimeout(toast.timeoutId);
439
-
440
- toast.timeoutId = setTimeout(() => toast.classList.remove('show'), 3000);
441
- }
442
-
443
- // Check server status
444
- async function checkServerStatus() {
445
- try {
446
- const res = await fetch(`${API_BASE}/health`);
447
- if (res.ok) {
448
- document.getElementById('status').textContent = '● Online';
449
- document.getElementById('status').style.background = 'rgba(52, 199, 89, 0.15)';
450
- document.getElementById('status').style.color = 'var(--ios-green)';
451
- }
452
- } catch {
453
- document.getElementById('status').textContent = '● Offline';
454
- document.getElementById('status').style.background = 'rgba(255, 59, 48, 0.15)';
455
- document.getElementById('status').style.color = 'var(--ios-red)';
456
- }
457
- }