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.
- package/ARCHITECTURE.md +255 -0
- package/README.md +0 -11
- package/change.sh +0 -0
- package/dist/vg-coder-bundle.js +42 -0
- package/gulpfile.js +111 -0
- package/package.json +19 -11
- package/scripts/postinstall.js +13 -3
- package/src/index.js +28 -220
- package/src/server/api-server.js +120 -428
- package/src/server/views/css/bubble.css +81 -0
- package/src/server/views/css/code-viewer.css +58 -0
- package/src/server/views/css/terminal.css +59 -155
- package/src/server/views/dashboard.css +78 -678
- package/src/server/views/dashboard.html +39 -278
- package/src/server/views/js/api.js +2 -22
- package/src/server/views/js/config.js +27 -15
- package/src/server/views/js/event-protocol.js +263 -0
- package/src/server/views/js/features/bubble-features/index.js +125 -0
- package/src/server/views/js/features/bubble-features/paste-run-feature.js +16 -0
- package/src/server/views/js/features/bubble-features/terminal-feature.js +16 -0
- package/src/server/views/js/features/bubble.js +175 -0
- package/src/server/views/js/features/code-viewer.js +90 -0
- package/src/server/views/js/features/commands.js +34 -81
- package/src/server/views/js/features/editor-tabs.js +19 -46
- package/src/server/views/js/features/git-view.js +63 -81
- package/src/server/views/js/features/iframe-manager.js +3 -97
- package/src/server/views/js/features/monaco-manager.js +19 -39
- package/src/server/views/js/features/project-switcher.js +7 -63
- package/src/server/views/js/features/resize.js +5 -16
- package/src/server/views/js/features/structure.js +38 -106
- package/src/server/views/js/features/terminal.js +102 -418
- package/src/server/views/js/handlers.js +60 -43
- package/src/server/views/js/main.js +75 -179
- package/src/server/views/js/shadow-entry.js +21 -0
- package/src/server/views/js/utils.js +48 -28
- package/src/server/views/vg-coder/_metadata/generated_indexed_rulesets/_ruleset1 +0 -0
- package/src/server/views/vg-coder/controller.js +33 -258
- package/vetgo-auto/chrome/src/utils/injector-script.ts +33 -258
- package/vetgo-auto/vg-coder.zip +0 -0
- package/src/server/views/dashboard.js +0 -457
|
@@ -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
|
-
|
|
8
|
-
|
|
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
|
-
|
|
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
|
|
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 echo 'Hello' > src/test/hello.txt"></textarea>
|
|
87
|
+
<textarea id="execute-bash" placeholder="mkdir -p src/test echo 'Hello' > src/test/hello.txt"></textarea>
|
|
159
88
|
</div>
|
|
160
89
|
<div class="btn-group">
|
|
161
|
-
<button class="btn" onclick="testExecute(event)">
|
|
162
|
-
|
|
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
|
-
|
|
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="
|
|
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
|
-
|
|
268
|
-
|
|
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) → <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
|
-
|
|
328
|
-
|
|
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
|
-
<!--
|
|
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
|
-
|
|
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
|
-
|
|
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ó
|
|
60
|
-
- ✅ Sử dụng
|
|
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
|
-
|
|
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
|
-
|
|
104
|
+
\`\`\`bash
|
|
94
105
|
POST http://localhost:6868/api/execute
|
|
95
106
|
{
|
|
96
|
-
"bash": "mkdir -p $(dirname
|
|
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
|
|
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
|
|
112
|
-
- Sử dụng
|
|
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
|
|
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`;
|