vg-coder-cli 2.0.31 → 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/src/index.js +28 -220
  8. package/src/server/api-server.js +120 -428
  9. package/src/server/views/css/bubble.css +81 -0
  10. package/src/server/views/css/code-viewer.css +58 -0
  11. package/src/server/views/css/terminal.css +59 -155
  12. package/src/server/views/dashboard.css +78 -678
  13. package/src/server/views/dashboard.html +39 -278
  14. package/src/server/views/js/api.js +2 -22
  15. package/src/server/views/js/config.js +27 -15
  16. package/src/server/views/js/event-protocol.js +263 -0
  17. package/src/server/views/js/features/bubble-features/index.js +125 -0
  18. package/src/server/views/js/features/bubble-features/paste-run-feature.js +16 -0
  19. package/src/server/views/js/features/bubble-features/terminal-feature.js +16 -0
  20. package/src/server/views/js/features/bubble.js +175 -0
  21. package/src/server/views/js/features/code-viewer.js +90 -0
  22. package/src/server/views/js/features/commands.js +34 -81
  23. package/src/server/views/js/features/editor-tabs.js +19 -46
  24. package/src/server/views/js/features/git-view.js +63 -81
  25. package/src/server/views/js/features/iframe-manager.js +3 -97
  26. package/src/server/views/js/features/monaco-manager.js +19 -39
  27. package/src/server/views/js/features/project-switcher.js +7 -63
  28. package/src/server/views/js/features/resize.js +5 -16
  29. package/src/server/views/js/features/structure.js +38 -106
  30. package/src/server/views/js/features/terminal.js +102 -418
  31. package/src/server/views/js/handlers.js +60 -43
  32. package/src/server/views/js/main.js +75 -179
  33. package/src/server/views/js/shadow-entry.js +21 -0
  34. package/src/server/views/js/utils.js +48 -28
  35. package/src/server/views/vg-coder/_metadata/generated_indexed_rulesets/_ruleset1 +0 -0
  36. package/src/server/views/vg-coder/controller.js +33 -258
  37. package/vetgo-auto/chrome/src/utils/injector-script.ts +33 -258
  38. package/vetgo-auto/vg-coder.zip +0 -0
  39. package/src/server/views/dashboard.js +0 -457
  40. package/test-pty.js +0 -31
@@ -1,73 +1,29 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
-
4
3
  <head>
5
4
  <meta charset="UTF-8">
6
- <meta name="viewport"
7
- content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
8
- <title>VG Coder - Split View</title>
9
- <link rel="stylesheet" href="/dashboard.css">
10
- <link rel="stylesheet" href="/css/structure.css">
11
- <link rel="stylesheet" href="/css/iframe.css">
12
- <link rel="stylesheet" href="/css/git-view.css">
13
- <link rel="stylesheet" href="/css/terminal.css">
14
- <link rel="stylesheet" href="/css/editor.css">
15
- <link rel="stylesheet" href="/css/monaco.css">
16
-
17
- <!-- Syntax Highlighting -->
18
- <link rel="stylesheet"
19
- href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css" />
20
-
21
- <!-- Git Diff CSS (JSDelivr Bundle) -->
22
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/diff2html@3.4.47/bundles/css/diff2html.min.css" />
23
-
24
- <!-- Terminal Dependencies -->
25
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" />
26
- <script src="/socket.io/socket.io.js"></script>
27
- <script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js"></script>
28
- <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js"></script>
29
-
30
- <!-- Monaco Editor Loader -->
31
- <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs/loader.min.js"></script>
32
-
33
- <!-- FIX: AMD Loader Conflict Patch -->
34
- <script>
35
- var __amdDefine = window.define;
36
- var __amdRequire = window.require;
37
- window.define = undefined;
38
- window.require = undefined;
39
- </script>
40
-
41
- <!-- Git Diff JS (JSDelivr Bundle) -->
42
- <script src="https://cdn.jsdelivr.net/npm/diff2html@3.4.47/bundles/js/diff2html-ui.min.js"></script>
43
-
44
- <!-- FIX: Restore AMD Loader -->
45
- <script>
46
- window.define = __amdDefine;
47
- window.require = __amdRequire;
48
- </script>
49
-
50
- <script>
51
- (function () {
52
- const savedTheme = localStorage.getItem('theme') || 'light';
53
- document.documentElement.setAttribute('data-theme', savedTheme);
54
- })();
55
- </script>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Service Worker</title>
7
+ <!-- CSS & JS Injected via Gulp -->
56
8
  </head>
9
+ <body style="display: none;">
10
+ <!-- BUBBLE INTERFACE -->
11
+ <div id="vg-bubble" class="vg-bubble" title="VG Coder (Click to Open, Drag to Move)">
12
+ <div class="vg-bubble-icon"><img style="width: 64px;" src="https://phanmemvet.vn/wp-content/vetgo/pawai.gif"></div>
13
+ <!-- Quick Action Menu (Shows on hover) - Features rendered dynamically by bubble.js -->
14
+ <div class="vg-bubble-menu">
15
+ <!-- Features rendered dynamically -->
16
+ </div>
17
+ </div>
57
18
 
58
- <body>
19
+ <!-- MAIN DASHBOARD INTERFACE -->
59
20
  <div class="split-layout">
60
- <!-- CỘT TRÁI: Giao diện VG Coder -->
61
21
  <div class="left-panel">
62
22
  <div class="container">
63
- <!-- Header Layout Redesign -->
64
23
  <div class="header">
65
- <!-- Top Row: Status, Switcher (Title), Actions -->
66
24
  <div class="header-top-row">
67
25
  <div class="header-left-group">
68
26
  <span class="status" id="status" style="font-size: 14px;">●</span>
69
-
70
- <!-- Project Switcher takes primary spot -->
71
27
  <div class="project-switcher">
72
28
  <select id="project-selector" class="project-selector" onchange="window.switchProject(this.value)" title="Switch Project">
73
29
  <option value="">Loading...</option>
@@ -75,62 +31,40 @@
75
31
  <span class="project-count" id="project-count">1 project</span>
76
32
  </div>
77
33
  </div>
78
-
79
- <!-- Right Actions -->
80
34
  <div class="header-actions">
81
- <button class="stop-server-btn" id="stop-server-btn" onclick="window.stopServer()" title="Stop Server">
82
- 🛑
83
- </button>
35
+ <button class="stop-server-btn" id="stop-server-btn" onclick="window.stopServer()" title="Stop Server">🛑</button>
84
36
  <button class="theme-toggle" id="theme-toggle" title="Toggle Dark Mode">
85
37
  <span id="theme-icon">🌙</span>
86
38
  </button>
87
39
  </div>
88
40
  </div>
89
-
90
- <!-- Bottom Row: Meta Info (Path/Type) -->
91
41
  <div class="header-bottom-row">
92
42
  <div class="project-meta" id="project-meta">...</div>
93
- <!-- Hidden element to keep JS happy -->
94
43
  <div id="project-name" style="display: none;"></div>
95
44
  </div>
96
45
  </div>
97
46
 
98
- <!-- Saved Commands Panel -->
47
+ <!-- Saved Commands -->
99
48
  <div class="endpoint-card saved-commands-panel">
100
49
  <div class="saved-commands-header">
101
- <div class="saved-commands-title">
102
- <span class="command-icon-header">💾</span>
103
- <span>Saved Commands</span>
104
- </div>
50
+ <div class="saved-commands-title"><span class="command-icon-header">💾</span><span>Saved Commands</span></div>
105
51
  <div class="saved-commands-actions">
106
- <button class="btn-new-terminal" onclick="createNewTerminal()" title="New Terminal">
107
- 🖥️
108
- </button>
109
- <button class="btn-add-command" onclick="openAddCommandModal()" title="Add Command">
110
-
111
- </button>
52
+ <button class="btn-new-terminal" onclick="createNewTerminal()" title="New Terminal">🖥️</button>
53
+ <button class="btn-add-command" onclick="openAddCommandModal()" title="Add Command">➕</button>
112
54
  </div>
113
55
  </div>
114
56
  <div class="saved-commands-content" id="saved-commands-content">
115
- <div id="commands-list" class="commands-list">
116
- <!-- Commands will be rendered here -->
117
- </div>
57
+ <div id="commands-list" class="commands-list"></div>
118
58
  <div class="empty-state" id="commands-empty-state" style="display: none;">
119
- <p style="color: #888; text-align: center; padding: 15px 10px; font-size: 12px; margin: 0;">
120
- Click ➕ to add a command
121
- </p>
59
+ <p style="color: #888; text-align: center; padding: 15px 10px; font-size: 12px; margin: 0;">Click ➕ to add a command</p>
122
60
  </div>
123
61
  </div>
124
62
  </div>
125
63
 
126
- <!-- System Prompt Section -->
127
64
  <div class="system-prompt-card">
128
65
  <div class="system-prompt-header" onclick="toggleSystemPrompt()">
129
66
  <div class="header-title-group">
130
- <button class="btn-icon-head" onclick="copySystemPromptFromHeader(event)"
131
- title="Copy System Prompt">
132
- 📋
133
- </button>
67
+ <button class="btn-icon-head" onclick="copySystemPromptFromHeader(event)" title="Copy System Prompt">📋</button>
134
68
  <h2>System Prompt</h2>
135
69
  </div>
136
70
  <span class="toggle-icon" id="toggle-icon">▼</span>
@@ -145,68 +79,45 @@
145
79
  </div>
146
80
 
147
81
  <div class="endpoints">
148
- <!-- Execute Bash -->
149
82
  <div class="endpoint-card">
150
83
  <div class="endpoint-header">
151
- <div class="endpoint-title-group">
152
- <span class="method post">POST</span>
153
- <span class="endpoint-path">/execute</span>
154
- </div>
84
+ <div class="endpoint-title-group"><span class="method post">POST</span><span class="endpoint-path">/execute</span></div>
155
85
  </div>
156
86
  <div class="form-group">
157
- <textarea id="execute-bash"
158
- placeholder="mkdir -p src/test&#10;echo 'Hello' > src/test/hello.txt"></textarea>
87
+ <textarea id="execute-bash" placeholder="mkdir -p src/test&#10;echo 'Hello' > src/test/hello.txt"></textarea>
159
88
  </div>
160
89
  <div class="btn-group">
161
- <button class="btn" onclick="testExecute(event)">
162
- <span>▶️</span> Run
163
- </button>
164
- <button class="btn" onclick="executeFromClipboard(event)">
165
- <span>📋</span> Paste & Run
166
- </button>
90
+ <button class="btn" onclick="testExecute(event)"><span>▶️</span> Run</button>
91
+ <button class="btn" onclick="executeFromClipboard(event)"><span>📋</span> Paste & Run</button>
167
92
  </div>
168
93
  <div class="response" id="execute-response"></div>
169
94
  </div>
170
95
 
171
- <!-- Structure -->
172
96
  <div class="endpoint-card">
173
97
  <div class="endpoint-header">
174
98
  <div class="endpoint-title-group">
175
99
  <span class="method get" style="background: var(--ios-blue); color: white;">GET</span>
176
100
  <span class="endpoint-path">/structure</span>
177
101
  </div>
178
- <button class="btn-icon-head" onclick="copySelectedStructure(event)" title="Copy Selected">
179
- 📋
180
- </button>
102
+ <button class="btn-icon-head" onclick="copySelectedStructure(event)" title="Copy Selected">📋</button>
181
103
  </div>
182
104
  <div class="form-group">
183
105
  <input type="text" id="structure-path" value="." placeholder="Project path">
184
106
  </div>
185
107
  <div class="btn-group">
186
- <button class="btn" onclick="testStructure(event)">
187
- <span>🌳</span> View
188
- </button>
108
+ <button class="btn" onclick="testStructure(event)"><span>🌳</span> View</button>
189
109
  </div>
190
110
  <div class="tree-container" id="structure-tree" style="display: none;">
191
- <div class="tree-header">
192
- <span>Tree</span>
193
- <span class="tree-total-tokens" id="total-tokens-badge">0 tokens</span>
194
- </div>
111
+ <div class="tree-header"><span>Tree</span><span class="tree-total-tokens" id="total-tokens-badge">0 tokens</span></div>
195
112
  <div class="tree-content" id="tree-content"></div>
196
113
  </div>
197
114
  <div class="response" id="structure-response" style="display: none;"></div>
198
115
  </div>
199
116
 
200
- <!-- Analyze -->
201
117
  <div class="endpoint-card">
202
118
  <div class="endpoint-header">
203
- <div class="endpoint-title-group">
204
- <span class="method post">POST</span>
205
- <span class="endpoint-path">/analyze</span>
206
- </div>
207
- <button class="btn-icon-head" onclick="testAnalyze(event)" title="Download Project Source">
208
- 📥
209
- </button>
119
+ <div class="endpoint-title-group"><span class="method post">POST</span><span class="endpoint-path">/analyze</span></div>
120
+ <button class="btn-icon-head" onclick="testAnalyze(event)" title="Download Project Source">📥</button>
210
121
  </div>
211
122
  <div class="form-group">
212
123
  <input type="text" id="analyze-path" value="." placeholder="Project path (e.g. .)">
@@ -223,118 +134,37 @@
223
134
  <div style="height: 50px;"></div>
224
135
  </div>
225
136
  </div>
226
- <!-- Resize Handler -->
227
137
  <div id="resize-handler" class="resize-handler"></div>
228
138
 
229
- <!-- CỘT PHẢI: AI Iframe & Editor -->
230
139
  <div class="right-panel">
231
- <!-- HEADER MỚI: Tích hợp Tabs & Actions -->
232
140
  <div id="tabs-header" class="tabs-header">
233
- <!-- Vùng Tabs Scrollable -->
234
141
  <div class="tabs-scroll-area">
235
-
236
- <!-- AI Tab (STATIC) -->
237
- <div class="tab-item active" id="ai-tab" onclick="window.switchTab('ai-assistant')"
238
- data-path="ai-assistant">
239
- <span class="tab-icon">🤖</span>
240
- <!-- Select Box nằm ngay trong tên Tab -->
241
- <select id="ai-provider-select" class="ai-provider-select" onclick="event.stopPropagation()">
242
- <!-- Options filled by JS -->
243
- </select>
244
- </div>
245
-
246
- <!-- Dynamic File Tabs -->
247
142
  <div id="file-tabs-container" style="display:flex; height:100%;"></div>
248
143
  </div>
249
-
250
- <!-- Global Actions -->
251
144
  <div class="tabs-actions">
252
- <button id="guide-toggle-btn" class="action-btn-mini" title="Show Installation Guide">🧩</button>
253
- <button id="git-refresh-btn" class="action-btn-mini" style="display:none;"
254
- title="Refresh Git">↻</button>
255
- <button id="git-view-toggle" class="action-btn-mini" title="Toggle Git View">
256
- <span style="font-size:12px">Git</span>
257
- </button>
145
+ <button id="git-view-toggle" class="action-btn-mini" title="Toggle Git View"><span style="font-size:12px">Git</span></button>
258
146
  </div>
259
147
  </div>
260
-
261
- <!-- Git View Container -->
262
148
  <div id="git-view-container" class="git-view-container"></div>
263
-
264
- <!-- Editor Container -->
265
149
  <div class="editor-container" style="flex: 1; position: relative; overflow: hidden;">
266
-
267
- <!-- AI Iframe -->
268
- <div class="ai-iframe-container">
269
- <div id="iframe-placeholder" class="iframe-placeholder hidden">
270
- <div class="extension-guide-center">
271
- <button class="guide-close-btn" id="guide-close-btn" title="Close Guide">×</button>
272
- <span class="guide-icon">🧩</span>
273
- <h3 class="guide-title">Cài đặt VG Coder Extension</h3>
274
- <p class="guide-desc">
275
- Không thấy trang web? AI Provider chặn hiển thị trong Iframe.<br>
276
- Hãy cài đặt Extension để bỏ qua các giới hạn này.
277
- </p>
278
- <ol class="guide-steps">
279
- <li class="guide-step">
280
- <span class="step-number">1</span>
281
- Copy link và dán vào tab mới:
282
- <div class="url-box">
283
- <input type="text" id="chrome-url-input-center" class="guide-input" readonly
284
- value="chrome://extensions" onclick="this.select()">
285
- <button class="guide-btn-copy" onclick="copyChromeUrl(event)">Copy</button>
286
- </div>
287
- </li>
288
- <li class="guide-step">
289
- <span class="step-number">2</span>
290
- Bật <b>Developer mode</b> (Góc phải trên) &rarr; <b>Load unpacked</b>
291
- </li>
292
- <li class="guide-step">
293
- <span class="step-number">3</span>
294
- Chọn thư mục bên dưới:
295
- <div class="path-box">
296
- <input type="text" id="extension-path-input-center" class="guide-input" readonly
297
- value="Loading..." onclick="this.select()">
298
- <button class="guide-btn-copy" onclick="copyExtensionPath(event)">Copy</button>
299
- </div>
300
- </li>
301
- </ol>
302
- <div class="guide-footer">
303
- <a id="ai-placeholder-link" href="#" target="_blank" class="link-fallback">Mở tab mới
304
- ↗</a>
305
- <button id="guide-done-btn" class="btn-primary-guide">Đã xong / Tải lại</button>
306
- </div>
307
- </div>
308
- </div>
309
- <iframe id="ai-iframe" src="" title="AI Integration"></iframe>
150
+ <!-- REPLACED MONACO WITH CODE VIEWER -->
151
+ <div id="code-viewer-container" class="code-viewer-container">
152
+ <div class="empty-editor">Select a file to view</div>
310
153
  </div>
311
-
312
- <!-- Monaco Editor Container -->
313
- <div id="monaco-container" class="monaco-container view-mode-hidden"></div>
314
154
  </div>
315
155
  </div>
316
156
  </div>
317
157
 
158
+ <!-- Modals & Overlays -->
318
159
  <div id="floating-terminals-layer"></div>
319
160
  <div class="toast" id="toast"></div>
320
-
321
- <!-- Add/Edit Command Modal -->
322
161
  <div id="command-modal" class="modal" style="display: none;">
323
162
  <div class="modal-content">
324
163
  <h3 id="modal-title">Add Command</h3>
325
164
  <form id="command-form">
326
- <div class="form-group">
327
- <label>Icon (emoji)</label>
328
- <input type="text" id="command-icon" placeholder="🚀" maxlength="2" required>
329
- </div>
330
- <div class="form-group">
331
- <label>Name</label>
332
- <input type="text" id="command-name" placeholder="Run Dev Server" required>
333
- </div>
334
- <div class="form-group">
335
- <label>Command</label>
336
- <input type="text" id="command-text" placeholder="npm run dev" required>
337
- </div>
165
+ <div class="form-group"><label>Icon (emoji)</label><input type="text" id="command-icon" placeholder="🚀" maxlength="2" required></div>
166
+ <div class="form-group"><label>Name</label><input type="text" id="command-name" placeholder="Run Dev Server" required></div>
167
+ <div class="form-group"><label>Command</label><input type="text" id="command-text" placeholder="npm run dev" required></div>
338
168
  <div class="modal-actions">
339
169
  <button type="button" class="btn" onclick="closeCommandModal()">Cancel</button>
340
170
  <button type="submit" class="btn btn-primary">Save</button>
@@ -343,75 +173,6 @@
343
173
  </div>
344
174
  </div>
345
175
 
346
- <!-- VG Coder Parent Context Detector -->
347
- <script>
348
- // Listener for nested iframe detection
349
- // When extension's controller.ts sends VG_CODER_PING, we reply with VG_CODER_PARENT
350
- window.addEventListener('message', (event) => {
351
- if (event.data?.type === 'VG_CODER_PING') {
352
- // Confirm this is VG Coder parent context
353
- event.source.postMessage({ type: 'VG_CODER_PARENT' }, '*');
354
- console.log('📡 Responded to VG_CODER_PING from iframe:', event.origin);
355
- }
356
- });
357
- </script>
358
-
359
- <!-- Embedded Mode Detection -->
360
- <script>
361
- // When dashboard is loaded with ?embedded=true (inside AI chat page),
362
- // hide the AI tab and iframe to prevent nested structure
363
- (function() {
364
- const urlParams = new URLSearchParams(window.location.search);
365
- const isEmbedded = urlParams.has('embedded');
366
-
367
- if (isEmbedded) {
368
- console.log('🎯 Embedded mode detected - hiding AI iframe tab');
369
-
370
- // Wait for DOM to be ready
371
- if (document.readyState === 'loading') {
372
- document.addEventListener('DOMContentLoaded', hideAITab);
373
- } else {
374
- hideAITab();
375
- }
376
-
377
- function hideAITab() {
378
- // Hide AI tab
379
- const aiTab = document.getElementById('ai-tab');
380
- if (aiTab) {
381
- aiTab.style.display = 'none';
382
- console.log('✅ AI tab hidden');
383
- }
384
-
385
- // Hide AI iframe container
386
- const aiContainer = document.querySelector('.ai-iframe-container');
387
- if (aiContainer) {
388
- aiContainer.style.display = 'none';
389
- console.log('✅ AI iframe container hidden');
390
- }
391
-
392
- // Switch to first editor tab if exists, or show monaco by default
393
- const fileTabsContainer = document.getElementById('file-tabs-container');
394
- if (fileTabsContainer && fileTabsContainer.children.length > 0) {
395
- // Click first file tab
396
- const firstTab = fileTabsContainer.children[0];
397
- if (firstTab) firstTab.click();
398
- } else {
399
- // Show monaco editor as default
400
- const monacoContainer = document.getElementById('monaco-container');
401
- if (monacoContainer) {
402
- monacoContainer.classList.remove('view-mode-hidden');
403
- }
404
- }
405
- }
406
- }
407
- })();
408
- </script>
409
-
410
- <!-- Smart Log Copy Utilities -->
411
- <script src="/js/utils/log-utils.js"></script>
412
- <script src="/js/utils/smart-copy-engine.js"></script>
413
-
414
- <script type="module" src="/js/main.js"></script>
176
+ <!-- Scripts injected via Gulp -->
415
177
  </body>
416
-
417
178
  </html>
@@ -42,8 +42,6 @@ export async function getStructure(path) {
42
42
  return await res.json();
43
43
  }
44
44
 
45
- // --- Git API Wrappers ---
46
-
47
45
  export async function getGitStatus() {
48
46
  const res = await fetch(`${API_BASE}/api/git/status`);
49
47
  if (!res.ok) throw new Error('Failed to fetch status');
@@ -100,8 +98,6 @@ export async function commitChanges(message) {
100
98
  return true;
101
99
  }
102
100
 
103
- // --- Tree State API ---
104
-
105
101
  export async function saveTreeState(excludedPaths) {
106
102
  const res = await fetch(`${API_BASE}/api/tree-state/save`, {
107
103
  method: 'POST',
@@ -124,27 +120,11 @@ export async function loadTreeState() {
124
120
  return await res.json();
125
121
  }
126
122
 
127
- // ------------------------
128
-
129
- export async function copyAsFile(filename, content) {
130
- const blob = new Blob([content], { type: "application/octet-stream" });
131
- const item = new ClipboardItem({
132
- [blob.type]: blob
133
- }, {
134
- type: "application/octet-stream",
135
- presentationStyle: "attachment",
136
- name: filename
137
- });
138
- await navigator.clipboard.write([item]);
139
- }
140
-
141
123
  export async function copyToClipboard(text) {
142
124
  try {
143
- const blob = new Blob([text], { type: 'text/plain' });
144
- const item = new ClipboardItem({ 'text/plain': blob });
145
- await navigator.clipboard.write([item]);
146
- } catch (err) {
147
125
  await navigator.clipboard.writeText(text);
126
+ } catch (err) {
127
+ throw new Error('Clipboard write failed');
148
128
  }
149
129
  }
150
130
 
@@ -1,5 +1,16 @@
1
1
  // Configuration & Constants
2
- export const API_BASE = window.location.origin;
2
+
3
+ // Kiểm tra biến global được set bởi Injector trong gulpfile.js
4
+ // Hoặc kiểm tra xem có chạy trong Iframe không (fallback)
5
+ const isInjected = (typeof window !== 'undefined' && window.__VG_CODER_ROOT__) ||
6
+ (document.getElementById('vg-coder-shadow-host'));
7
+
8
+ console.log('[Config] VG Coder Context:', isInjected ? 'Injected (Shadow DOM)' : 'Standalone');
9
+
10
+ // QUAN TRỌNG: Nếu là Injected thì MẶC ĐỊNH trỏ về localhost:6868
11
+ // Nếu không, dùng relative path (cho trường hợp mở dashboard trực tiếp)
12
+ export const API_BASE = isInjected ? 'http://localhost:6868' : window.location.origin;
13
+
3
14
 
4
15
  // System Prompt
5
16
  export const SYSTEM_PROMPT = `# VG Coder AI System Prompt
@@ -48,23 +59,23 @@ Khi người dùng hỏi với prefix /code, trả về **BASH SCRIPT DUY NHẤT
48
59
  ### 2. Format Script Chuẩn
49
60
 
50
61
  **Mỗi file PHẢI theo cú pháp:**
51
- \\\`\\\`\\\`bash
62
+ \`\`\`bash
52
63
  mkdir -p $(dirname "path/to/file.ext")
53
64
  cat <<'EOF' > path/to/file.ext
54
65
  ... toàn bộ nội dung file sau khi chỉnh sửa ...
55
66
  EOF
56
- \\\`\\\`\\\`
67
+ \`\`\`
57
68
 
58
69
  ### 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
70
+ - ✅ **LUÔN** có \`mkdir -p $(dirname "...")\` trước mỗi file
71
+ - ✅ Sử dụng \`<<'EOF'\` (có dấu nháy đơn) để tránh bash expansion
61
72
  - ✅ Ghi đè hoàn toàn file bằng nội dung mới
62
73
  - ✅ Tự động tạo file và thư mục cha nếu chưa tồn tại
63
74
  - ✅ Đường dẫn giống với file mẫu đính kèm
64
75
 
65
76
  ### 4. Example Output
66
77
 
67
- \\\`\\\`\\\`bash
78
+ \`\`\`bash
68
79
  # Create/Update component file
69
80
  mkdir -p $(dirname "src/components/Button/index.tsx")
70
81
  cat <<'EOF' > src/components/Button/index.tsx
@@ -83,22 +94,23 @@ cat <<'EOF' > src/components/Button/styles.css
83
94
  background: blue;
84
95
  }
85
96
  EOF
86
- \\\`\\\`\\\`
97
+ \`\`\`
87
98
 
88
99
  ---
89
100
 
90
101
  ## Integration với VG Coder CLI
91
102
 
92
103
  Bash scripts được generate sẽ được thực thi qua:
93
- \\\`\\\`\\\`bash
104
+ \`\`\`bash
94
105
  POST http://localhost:6868/api/execute
95
106
  {
96
- "bash": "mkdir -p $(dirname \\\\"src/...\\\\")\\\\\\\ncat <<'EOF' > ..."
107
+ "bash": "mkdir -p $(dirname \\"src/...\\")\\\
108
+ cat <<'EOF' > ..."
97
109
  }
98
- \\\`\\\`\\\`
110
+ \`\`\`
99
111
 
100
112
  API sẽ:
101
- 1. ✅ Validate bash syntax trong \\\`.vg/temp-execute\\\`
113
+ 1. ✅ Validate bash syntax trong \`.vg/temp-execute\`
102
114
  2. ✅ Execute tại working directory nếu syntax OK
103
115
  3. ✅ Trả về stdout/stderr/exitCode
104
116
  4. ✅ Auto cleanup temp directory
@@ -108,13 +120,13 @@ API sẽ:
108
120
  ## Best Practices
109
121
 
110
122
  ### DO ✅
111
- - Luôn dùng \\\`mkdir -p $(dirname "...")\\\` trước mỗi file
112
- - Sử dụng \\\`<<'EOF'\\\` để tránh variable expansion
123
+ - Luôn dùng \`mkdir -p $(dirname "...")\` trước mỗi file
124
+ - Sử dụng \`<<'EOF'\` để tránh variable expansion
113
125
  - Ghi đè toàn bộ nội dung file
114
126
  - Chỉ include files có thay đổi thực sự
115
127
 
116
128
  ### DON'T ❌
117
129
  - 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
130
+ - Không dùng \`<<EOF\` (thiếu quotes) nếu có \`$\` trong content
119
131
  - Không include files không thay đổi
120
- - Không dùng relative paths phức tạp`;
132
+ - Không dùng relative paths phức tạp`;