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.
Files changed (50) hide show
  1. package/.vg/tree-state.json +9 -0
  2. package/package.json +5 -2
  3. package/scripts/build.js +49 -6
  4. package/src/index.js +4 -4
  5. package/src/server/api-server.js +83 -5
  6. package/src/server/views/css/structure.css +4 -1
  7. package/src/server/views/dashboard.css +51 -6
  8. package/src/server/views/dashboard.html +11 -3
  9. package/src/server/views/js/api.js +24 -0
  10. package/src/server/views/js/features/iframe-manager.js +2 -1
  11. package/src/server/views/js/features/resize.js +57 -0
  12. package/src/server/views/js/features/structure.js +109 -16
  13. package/src/server/views/js/main.js +36 -4
  14. package/src/server/views/vg-coder/background.js +48201 -2
  15. package/src/server/views/vg-coder/controller.js +496 -1
  16. package/src/server/views/vg-coder/manifest.json +13 -5
  17. package/src/server/views/vg-coder/{options.css → sidepanel.css} +34 -32
  18. package/src/server/views/vg-coder/{options.html → sidepanel.html} +2 -2
  19. package/src/server/views/vg-coder/sidepanel.js +347 -0
  20. package/vetgo-auto/README.md +3 -0
  21. package/vetgo-auto/chrome/CSP_IMPROVEMENTS.md +147 -0
  22. package/vetgo-auto/chrome/MANIFEST_V3_MIGRATION.md +123 -0
  23. package/vetgo-auto/chrome/assets/icon128.png +0 -0
  24. package/vetgo-auto/chrome/assets/icon16.png +0 -0
  25. package/vetgo-auto/chrome/assets/icon48.png +0 -0
  26. package/vetgo-auto/chrome/environments/environment.ts +13 -0
  27. package/vetgo-auto/chrome/manifest.json +66 -0
  28. package/vetgo-auto/chrome/rules.json +23 -0
  29. package/vetgo-auto/chrome/src/background.ts +200 -0
  30. package/vetgo-auto/chrome/src/controller.ts +98 -0
  31. package/vetgo-auto/chrome/src/controllers/common.firebase.ts +31 -0
  32. package/vetgo-auto/chrome/src/controllers/firebase-crud.ts +147 -0
  33. package/vetgo-auto/chrome/src/controllers/load-common-fuc.controller.ts +24 -0
  34. package/vetgo-auto/chrome/src/controllers/load-script.controller.ts +23 -0
  35. package/vetgo-auto/chrome/src/script-injector.ts +305 -0
  36. package/vetgo-auto/chrome/src/sidepanel.css +166 -0
  37. package/vetgo-auto/chrome/src/sidepanel.html +48 -0
  38. package/vetgo-auto/chrome/src/sidepanel.ts +127 -0
  39. package/vetgo-auto/chrome/src/utils/db-utils.ts +2 -0
  40. package/vetgo-auto/chrome/src/utils/environment-storage.service.ts +85 -0
  41. package/vetgo-auto/chrome/webpack.config.js +53 -0
  42. package/vetgo-auto/chrome/webpack.config.prod.js +54 -0
  43. package/vetgo-auto/package.json +30 -0
  44. package/vetgo-auto/tsconfig.json +27 -0
  45. package/vg-coder-cli-2.0.23.tgz +0 -0
  46. package/src/server/views/vg-coder/background.js.LICENSE.txt +0 -118
  47. package/src/server/views/vg-coder/options.js +0 -1
  48. package/vg-coder-cli-2.0.20.tgz +0 -0
  49. package/vg-coder-cli-2.0.21.tgz +0 -0
  50. 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
- // 1. Sync Children: If this is a folder, update all children checkboxes
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
- // 2. Recalculate Tokens
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
- const isDir = node.type === 'directory';
173
- const hasChildren = isDir && node.children && node.children.length > 0;
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
- // Determine Token Color
176
- const tokens = node.tokens || 0;
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 = (node.relativePath || node.path).replace(/\\/g, '\\\\');
200
- clickAction = `onclick="window.openFileTab('${safePath}', '${node.name}')"`;
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="${node.relativePath || node.path}"
262
+ data-path="${nodePath}"
212
263
  data-tokens="${tokens}"
213
- data-type="${node.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 : ''}>${node.name}</span>
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
- node.children.forEach(child => {
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 = '● Online';
50
- statusEl.style.background = 'rgba(52, 199, 89, 0.15)';
57
+ statusEl.textContent = '●';
58
+ statusEl.style.background = 'transparent';
51
59
  statusEl.style.color = 'var(--ios-green)';
52
60
  } else {
53
- statusEl.textContent = '● Offline';
54
- statusEl.style.background = 'rgba(255, 59, 48, 0.15)';
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';