vg-coder-cli 2.0.20 → 2.0.23
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/.vg/tree-state.json +9 -0
- package/package.json +5 -2
- package/scripts/build.js +49 -6
- package/src/index.js +4 -4
- package/src/server/api-server.js +83 -5
- package/src/server/views/css/structure.css +4 -1
- package/src/server/views/dashboard.css +51 -6
- package/src/server/views/dashboard.html +11 -3
- package/src/server/views/js/api.js +24 -0
- package/src/server/views/js/features/iframe-manager.js +2 -1
- package/src/server/views/js/features/resize.js +57 -0
- package/src/server/views/js/features/structure.js +109 -16
- package/src/server/views/js/main.js +36 -4
- package/src/server/views/vg-coder/background.js +48201 -2
- package/src/server/views/vg-coder/controller.js +496 -1
- package/src/server/views/vg-coder/manifest.json +13 -5
- package/src/server/views/vg-coder/{options.css → sidepanel.css} +34 -32
- package/src/server/views/vg-coder/{options.html → sidepanel.html} +2 -2
- package/src/server/views/vg-coder/sidepanel.js +347 -0
- package/vetgo-auto/README.md +3 -0
- package/vetgo-auto/chrome/CSP_IMPROVEMENTS.md +147 -0
- package/vetgo-auto/chrome/MANIFEST_V3_MIGRATION.md +123 -0
- package/vetgo-auto/chrome/assets/icon128.png +0 -0
- package/vetgo-auto/chrome/assets/icon16.png +0 -0
- package/vetgo-auto/chrome/assets/icon48.png +0 -0
- package/vetgo-auto/chrome/environments/environment.ts +13 -0
- package/vetgo-auto/chrome/manifest.json +66 -0
- package/vetgo-auto/chrome/rules.json +23 -0
- package/vetgo-auto/chrome/src/background.ts +200 -0
- package/vetgo-auto/chrome/src/controller.ts +98 -0
- package/vetgo-auto/chrome/src/controllers/common.firebase.ts +31 -0
- package/vetgo-auto/chrome/src/controllers/firebase-crud.ts +147 -0
- package/vetgo-auto/chrome/src/controllers/load-common-fuc.controller.ts +24 -0
- package/vetgo-auto/chrome/src/controllers/load-script.controller.ts +23 -0
- package/vetgo-auto/chrome/src/script-injector.ts +305 -0
- package/vetgo-auto/chrome/src/sidepanel.css +166 -0
- package/vetgo-auto/chrome/src/sidepanel.html +48 -0
- package/vetgo-auto/chrome/src/sidepanel.ts +127 -0
- package/vetgo-auto/chrome/src/utils/db-utils.ts +2 -0
- package/vetgo-auto/chrome/src/utils/environment-storage.service.ts +85 -0
- package/vetgo-auto/chrome/webpack.config.js +53 -0
- package/vetgo-auto/chrome/webpack.config.prod.js +54 -0
- package/vetgo-auto/package.json +30 -0
- package/vetgo-auto/tsconfig.json +27 -0
- package/vg-coder-cli-2.0.23.tgz +0 -0
- package/src/server/views/vg-coder/background.js.LICENSE.txt +0 -118
- package/src/server/views/vg-coder/options.js +0 -1
- package/vg-coder-cli-2.0.20.tgz +0 -0
- package/vg-coder-cli-2.0.21.tgz +0 -0
- package/vg-coder.zip +0 -0
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { getStructure, analyzeProject, copyToClipboard } from '../api.js';
|
|
1
|
+
import { getStructure, analyzeProject, copyToClipboard, saveTreeState as apiSaveTreeState, loadTreeState as apiLoadTreeState } from '../api.js';
|
|
2
2
|
import { showToast, showLoading, resetButton, showResponse, formatNumber, showCopiedState } from '../utils.js';
|
|
3
3
|
|
|
4
4
|
// Global variable to store current structure data
|
|
5
5
|
let currentStructureData = null;
|
|
6
6
|
|
|
7
|
+
// Tree state management
|
|
8
|
+
let excludedPaths = new Set(); // Paths that are unchecked
|
|
9
|
+
let saveStateTimeout = null; // Debounce timer for auto-save
|
|
10
|
+
|
|
7
11
|
/**
|
|
8
12
|
* Handle Structure button click logic
|
|
9
13
|
*/
|
|
@@ -24,6 +28,9 @@ export async function handleStructureView(event) {
|
|
|
24
28
|
const data = await getStructure(path);
|
|
25
29
|
currentStructureData = data.structure;
|
|
26
30
|
|
|
31
|
+
// Load saved state before rendering
|
|
32
|
+
await loadTreeState();
|
|
33
|
+
|
|
27
34
|
// Render Tree HTML using recursive function
|
|
28
35
|
treeContent.innerHTML = generateTreeHtml(data.structure);
|
|
29
36
|
|
|
@@ -62,18 +69,35 @@ export function handleCheckboxChange(event) {
|
|
|
62
69
|
event.stopPropagation();
|
|
63
70
|
const checkbox = event.target;
|
|
64
71
|
const isChecked = checkbox.checked;
|
|
72
|
+
const path = checkbox.dataset.path;
|
|
73
|
+
|
|
74
|
+
// 1. Update excluded paths set
|
|
75
|
+
if (isChecked) {
|
|
76
|
+
excludedPaths.delete(path);
|
|
77
|
+
} else {
|
|
78
|
+
excludedPaths.add(path);
|
|
79
|
+
}
|
|
65
80
|
|
|
66
|
-
//
|
|
81
|
+
// 2. Sync Children: If this is a folder, update all children checkboxes
|
|
67
82
|
const li = checkbox.closest('.tree-li');
|
|
68
83
|
if (li) {
|
|
69
84
|
const childrenCheckboxes = li.querySelectorAll('.tree-checkbox');
|
|
70
85
|
childrenCheckboxes.forEach(child => {
|
|
71
86
|
child.checked = isChecked;
|
|
87
|
+
const childPath = child.dataset.path;
|
|
88
|
+
if (isChecked) {
|
|
89
|
+
excludedPaths.delete(childPath);
|
|
90
|
+
} else {
|
|
91
|
+
excludedPaths.add(childPath);
|
|
92
|
+
}
|
|
72
93
|
});
|
|
73
94
|
}
|
|
74
95
|
|
|
75
|
-
//
|
|
96
|
+
// 3. Recalculate Tokens
|
|
76
97
|
updateTotalTokens();
|
|
98
|
+
|
|
99
|
+
// 4. Auto-save state (debounced)
|
|
100
|
+
debouncedSaveState();
|
|
77
101
|
}
|
|
78
102
|
|
|
79
103
|
/**
|
|
@@ -169,11 +193,35 @@ export async function handleCopySelected(event) {
|
|
|
169
193
|
function generateTreeHtml(node) {
|
|
170
194
|
if (!node) return '';
|
|
171
195
|
|
|
172
|
-
|
|
173
|
-
|
|
196
|
+
// --- COMPACT FOLDER LOGIC ---
|
|
197
|
+
let currentNode = node;
|
|
198
|
+
let displayName = node.name;
|
|
199
|
+
let isCompact = false;
|
|
200
|
+
|
|
201
|
+
// Only compact if it's a directory
|
|
202
|
+
if (currentNode.type === 'directory') {
|
|
203
|
+
// While current node has EXACTLY one child and that child is a directory
|
|
204
|
+
while (
|
|
205
|
+
currentNode.children &&
|
|
206
|
+
currentNode.children.length === 1 &&
|
|
207
|
+
currentNode.children[0].type === 'directory'
|
|
208
|
+
) {
|
|
209
|
+
const child = currentNode.children[0];
|
|
210
|
+
displayName += '/' + child.name;
|
|
211
|
+
currentNode = child; // Advance to child
|
|
212
|
+
isCompact = true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Now uses 'currentNode' for properties (it's the deepest folder in the chain)
|
|
217
|
+
// But we use 'displayName' for the UI
|
|
218
|
+
// 'tokens' should be from the root node of this chain (usually same as leaf for folders)
|
|
174
219
|
|
|
175
|
-
|
|
176
|
-
const
|
|
220
|
+
const isDir = currentNode.type === 'directory';
|
|
221
|
+
const hasChildren = isDir && currentNode.children && currentNode.children.length > 0;
|
|
222
|
+
|
|
223
|
+
// Determine Token Color (Use original node's tokens or deep node's tokens - they should be identical)
|
|
224
|
+
const tokens = currentNode.tokens || 0;
|
|
177
225
|
let tokenClass = 'token-low';
|
|
178
226
|
if (tokens > 5000) tokenClass = 'token-high';
|
|
179
227
|
else if (tokens > 2000) tokenClass = 'token-med';
|
|
@@ -184,7 +232,6 @@ function generateTreeHtml(node) {
|
|
|
184
232
|
const liClass = `tree-li ${hasChildren ? 'has-children' : ''}`;
|
|
185
233
|
|
|
186
234
|
// Actions
|
|
187
|
-
// On click: Toggle if folder, Open Tab if file
|
|
188
235
|
let clickAction = '';
|
|
189
236
|
let cursorStyle = '';
|
|
190
237
|
|
|
@@ -196,34 +243,38 @@ function generateTreeHtml(node) {
|
|
|
196
243
|
} else {
|
|
197
244
|
// File click -> Open in Editor
|
|
198
245
|
// Escape backslashes for Windows paths
|
|
199
|
-
const safePath = (
|
|
200
|
-
clickAction = `onclick="window.openFileTab('${safePath}', '${
|
|
246
|
+
const safePath = (currentNode.relativePath || currentNode.path).replace(/\\/g, '\\\\');
|
|
247
|
+
clickAction = `onclick="window.openFileTab('${safePath}', '${currentNode.name}')"`;
|
|
201
248
|
cursorStyle = 'cursor: pointer; color: var(--text-primary);';
|
|
202
249
|
}
|
|
203
250
|
|
|
204
251
|
// Build HTML
|
|
205
252
|
let html = `<li class="${liClass}">`;
|
|
206
253
|
|
|
254
|
+
// Check if this path should be excluded (unchecked)
|
|
255
|
+
const nodePath = currentNode.relativePath || currentNode.path;
|
|
256
|
+
const isExcluded = excludedPaths.has(nodePath);
|
|
257
|
+
|
|
207
258
|
html += `
|
|
208
259
|
<div class="tree-item-row" ${isDir ? clickAction : ''}>
|
|
209
260
|
<span class="arrow">${arrow}</span>
|
|
210
261
|
<input type="checkbox" class="tree-checkbox"
|
|
211
|
-
data-path="${
|
|
262
|
+
data-path="${nodePath}"
|
|
212
263
|
data-tokens="${tokens}"
|
|
213
|
-
data-type="${
|
|
214
|
-
checked
|
|
264
|
+
data-type="${currentNode.type}"
|
|
265
|
+
${isExcluded ? '' : 'checked'}
|
|
215
266
|
onclick="handleCheckboxChange(event)">
|
|
216
267
|
<span class="tree-icon">${icon}</span>
|
|
217
|
-
<span class="tree-name" style="${cursorStyle}" ${!isDir ? clickAction : ''}>${
|
|
268
|
+
<span class="tree-name" style="${cursorStyle}" ${!isDir ? clickAction : ''} title="${displayName}">${displayName}</span>
|
|
218
269
|
<span class="token-badge ${tokenClass}">${formatNumber(tokens)}</span>
|
|
219
270
|
</div>
|
|
220
271
|
`;
|
|
221
272
|
|
|
222
|
-
// Children recursion
|
|
273
|
+
// Children recursion (using deepest node's children)
|
|
223
274
|
if (hasChildren) {
|
|
224
275
|
html += '<ul class="tree-ul">';
|
|
225
276
|
// Sort: Folders first, then files
|
|
226
|
-
|
|
277
|
+
currentNode.children.forEach(child => {
|
|
227
278
|
html += generateTreeHtml(child);
|
|
228
279
|
});
|
|
229
280
|
html += '</ul>';
|
|
@@ -233,3 +284,45 @@ function generateTreeHtml(node) {
|
|
|
233
284
|
|
|
234
285
|
return isDir ? `<ul class="tree-ul">${html}</ul>` : html;
|
|
235
286
|
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Load tree state from backend
|
|
290
|
+
*/
|
|
291
|
+
async function loadTreeState() {
|
|
292
|
+
try {
|
|
293
|
+
const data = await apiLoadTreeState();
|
|
294
|
+
excludedPaths = new Set(data.excludedPaths || []);
|
|
295
|
+
console.log(`Loaded tree state: ${excludedPaths.size} excluded items`);
|
|
296
|
+
} catch (err) {
|
|
297
|
+
console.error('Failed to load tree state:', err);
|
|
298
|
+
excludedPaths = new Set(); // Reset to empty on error
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Debounced save - waits 500ms after last change before saving
|
|
304
|
+
*/
|
|
305
|
+
function debouncedSaveState() {
|
|
306
|
+
// Clear existing timeout
|
|
307
|
+
if (saveStateTimeout) {
|
|
308
|
+
clearTimeout(saveStateTimeout);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Set new timeout
|
|
312
|
+
saveStateTimeout = setTimeout(() => {
|
|
313
|
+
saveTreeState();
|
|
314
|
+
}, 500);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Save current tree state to backend
|
|
319
|
+
*/
|
|
320
|
+
async function saveTreeState() {
|
|
321
|
+
try {
|
|
322
|
+
const excludedArray = Array.from(excludedPaths);
|
|
323
|
+
await apiSaveTreeState(excludedArray);
|
|
324
|
+
console.log(`Saved tree state: ${excludedArray.length} excluded items`);
|
|
325
|
+
} catch (err) {
|
|
326
|
+
console.error('Failed to save tree state:', err);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
@@ -8,6 +8,7 @@ import { initGitView } from './features/git-view.js';
|
|
|
8
8
|
import { initTerminal, createNewTerminal } from './features/terminal.js';
|
|
9
9
|
import { initEditorTabs } from './features/editor-tabs.js';
|
|
10
10
|
import { initMonaco, updateMonacoTheme } from './features/monaco-manager.js';
|
|
11
|
+
import { initResizeHandler } from './features/resize.js';
|
|
11
12
|
|
|
12
13
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
13
14
|
// Load system prompt text
|
|
@@ -16,6 +17,9 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
|
16
17
|
// Check server status
|
|
17
18
|
await checkServerStatus();
|
|
18
19
|
|
|
20
|
+
// Load Project Info
|
|
21
|
+
await loadProjectInfo();
|
|
22
|
+
|
|
19
23
|
// Initialize Theme
|
|
20
24
|
initTheme();
|
|
21
25
|
|
|
@@ -31,9 +35,13 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
|
31
35
|
// Initialize Terminal System
|
|
32
36
|
initTerminal();
|
|
33
37
|
|
|
38
|
+
// Initialize Monaco & Tabs
|
|
34
39
|
// Initialize Monaco & Tabs
|
|
35
40
|
initMonaco();
|
|
36
41
|
initEditorTabs();
|
|
42
|
+
|
|
43
|
+
// Initialize Resize Handler
|
|
44
|
+
initResizeHandler();
|
|
37
45
|
|
|
38
46
|
// Set default tab to AI Assistant
|
|
39
47
|
if (window.switchTab) {
|
|
@@ -46,16 +54,40 @@ async function checkServerStatus() {
|
|
|
46
54
|
const isHealthy = await checkHealth();
|
|
47
55
|
|
|
48
56
|
if (isHealthy) {
|
|
49
|
-
statusEl.textContent = '●
|
|
50
|
-
statusEl.style.background = '
|
|
57
|
+
statusEl.textContent = '●';
|
|
58
|
+
statusEl.style.background = 'transparent';
|
|
51
59
|
statusEl.style.color = 'var(--ios-green)';
|
|
52
60
|
} else {
|
|
53
|
-
statusEl.textContent = '●
|
|
54
|
-
statusEl.style.background = '
|
|
61
|
+
statusEl.textContent = '●';
|
|
62
|
+
statusEl.style.background = 'transparent';
|
|
55
63
|
statusEl.style.color = 'var(--ios-red)';
|
|
56
64
|
}
|
|
57
65
|
}
|
|
58
66
|
|
|
67
|
+
async function loadProjectInfo() {
|
|
68
|
+
try {
|
|
69
|
+
// Fetch info for current directory (.)
|
|
70
|
+
const res = await fetch('/api/info?path=.');
|
|
71
|
+
const data = await res.json();
|
|
72
|
+
|
|
73
|
+
const projectNameEl = document.getElementById('project-name');
|
|
74
|
+
const projectMetaEl = document.getElementById('project-meta');
|
|
75
|
+
|
|
76
|
+
// Extract folder name from path
|
|
77
|
+
const fullPath = data.path;
|
|
78
|
+
// Handle both Windows (\) and Unix (/) paths
|
|
79
|
+
const folderName = fullPath.split(/[\\/]/).pop();
|
|
80
|
+
|
|
81
|
+
projectNameEl.textContent = folderName;
|
|
82
|
+
projectMetaEl.textContent = `${data.primaryType} • ${fullPath}`;
|
|
83
|
+
|
|
84
|
+
} catch (err) {
|
|
85
|
+
console.error('Failed to load project info:', err);
|
|
86
|
+
document.getElementById('project-name').textContent = 'Unknown Project';
|
|
87
|
+
document.getElementById('project-meta').textContent = 'Error loading info';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
59
91
|
function initTheme() {
|
|
60
92
|
const themeBtn = document.getElementById('theme-toggle');
|
|
61
93
|
let currentTheme = localStorage.getItem('theme') || 'light';
|