vg-coder-cli 2.0.40 → 2.0.42

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.
@@ -0,0 +1,130 @@
1
+ import { getById } from '../utils.js';
2
+
3
+ const STORAGE_KEY_BROWSER_URL = 'vg-coder-browser-url';
4
+ const DEFAULT_URL = 'https://www.google.com';
5
+
6
+ /**
7
+ * Initialize Browser Panel
8
+ */
9
+ export function initBrowserPanel() {
10
+ // Listen for panel open event
11
+ document.addEventListener('tool-panel-opened', (e) => {
12
+ if (e.detail.panelId === 'browser' && e.detail.side === 'right') {
13
+ renderBrowserPanel();
14
+ }
15
+ });
16
+
17
+ console.log('[BrowserPanel] Initialized');
18
+ }
19
+
20
+ /**
21
+ * Render browser panel content
22
+ */
23
+ function renderBrowserPanel() {
24
+ const container = getById('browser-panel-content');
25
+ if (!container) {
26
+ console.error('[BrowserPanel] Container not found');
27
+ return;
28
+ }
29
+
30
+ // Check if already rendered
31
+ if (container.querySelector('.browser-panel-wrapper')) {
32
+ return;
33
+ }
34
+
35
+ // Get saved URL or use default
36
+ const savedUrl = localStorage.getItem(STORAGE_KEY_BROWSER_URL) || DEFAULT_URL;
37
+
38
+ // Create browser panel UI
39
+ container.innerHTML = `
40
+ <div class="browser-panel-wrapper">
41
+ <div class="browser-toolbar">
42
+ <input
43
+ type="text"
44
+ id="browser-url-input"
45
+ class="browser-url-input"
46
+ placeholder="Enter URL..."
47
+ value="${savedUrl}"
48
+ />
49
+ <button id="browser-go-btn" class="browser-go-btn" title="Go">→</button>
50
+ <button id="browser-refresh-btn" class="browser-refresh-btn" title="Refresh">🔄</button>
51
+ </div>
52
+ <iframe
53
+ id="browser-iframe"
54
+ class="browser-iframe"
55
+ src="${savedUrl}"
56
+ sandbox="allow-same-origin allow-scripts allow-forms allow-popups"
57
+ ></iframe>
58
+ </div>
59
+ `;
60
+
61
+ // Attach event listeners
62
+ attachBrowserListeners();
63
+
64
+ console.log('[BrowserPanel] Rendered with URL:', savedUrl);
65
+ }
66
+
67
+ /**
68
+ * Attach event listeners for browser controls
69
+ */
70
+ function attachBrowserListeners() {
71
+ const urlInput = getById('browser-url-input');
72
+ const goBtn = getById('browser-go-btn');
73
+ const refreshBtn = getById('browser-refresh-btn');
74
+ const iframe = getById('browser-iframe');
75
+
76
+ if (!urlInput || !goBtn || !iframe) {
77
+ console.error('[BrowserPanel] UI elements not found');
78
+ return;
79
+ }
80
+
81
+ // Navigate on button click
82
+ goBtn.addEventListener('click', () => {
83
+ navigateToUrl(urlInput.value, iframe);
84
+ });
85
+
86
+ // Navigate on Enter key
87
+ urlInput.addEventListener('keypress', (e) => {
88
+ if (e.key === 'Enter') {
89
+ navigateToUrl(urlInput.value, iframe);
90
+ }
91
+ });
92
+
93
+ // Refresh iframe
94
+ if (refreshBtn) {
95
+ refreshBtn.addEventListener('click', () => {
96
+ iframe.src = iframe.src; // Reload current URL
97
+ });
98
+ }
99
+
100
+ console.log('[BrowserPanel] Event listeners attached');
101
+ }
102
+
103
+ /**
104
+ * Navigate to URL
105
+ */
106
+ function navigateToUrl(url, iframe) {
107
+ if (!url) return;
108
+
109
+ // Add protocol if missing
110
+ let finalUrl = url;
111
+ if (!url.startsWith('http://') && !url.startsWith('https://')) {
112
+ finalUrl = 'https://' + url;
113
+ }
114
+
115
+ try {
116
+ iframe.src = finalUrl;
117
+ // Save URL to localStorage
118
+ localStorage.setItem(STORAGE_KEY_BROWSER_URL, finalUrl);
119
+
120
+ // Update input with final URL
121
+ const urlInput = getById('browser-url-input');
122
+ if (urlInput) {
123
+ urlInput.value = finalUrl;
124
+ }
125
+
126
+ console.log('[BrowserPanel] Navigated to:', finalUrl);
127
+ } catch (e) {
128
+ console.error('[BrowserPanel] Navigation failed:', e);
129
+ }
130
+ }
@@ -1,6 +1,6 @@
1
1
  import { getById, qsa, showToast } from '../utils.js';
2
2
  import { getGitDiff } from '../api.js';
3
- import { Diff2HtmlUI } from 'diff2html/lib/ui/js/diff2html-ui';
3
+ import { Diff2HtmlUI } from 'diff2html/lib-esm/src/ui/js/diff2html-ui';
4
4
 
5
5
  let isGitMode = false;
6
6
 
@@ -101,7 +101,7 @@ function isFromVGCoder(event) {
101
101
  /**
102
102
  * Toggle VG Coder dashboard visibility
103
103
  */
104
- function toggleDashboard() {
104
+ export function toggleDashboard() {
105
105
  const appRoot = getById('vg-app-root');
106
106
  if (!appRoot) {
107
107
  console.warn('[Keyboard] Cannot toggle dashboard: vg-app-root not found');
@@ -1,6 +1,50 @@
1
1
  import { qs, getById } from '../utils.js';
2
2
 
3
+ const STORAGE_KEY_LEFT_WIDTH = 'vg-coder-left-panel-width';
4
+ const STORAGE_KEY_RIGHT_WIDTH = 'vg-coder-right-panel-width';
5
+
3
6
  export function initResizeHandler() {
7
+ initLeftResizeHandler();
8
+ initRightResizeHandler();
9
+ loadSavedWidths();
10
+ }
11
+
12
+ /**
13
+ * Load saved panel widths from localStorage
14
+ */
15
+ function loadSavedWidths() {
16
+ const leftWidth = localStorage.getItem(STORAGE_KEY_LEFT_WIDTH);
17
+ const rightWidth = localStorage.getItem(STORAGE_KEY_RIGHT_WIDTH);
18
+
19
+ const leftContainer = getById('tool-panel-container');
20
+ const rightContainer = getById('tool-panel-container-right');
21
+
22
+ if (leftWidth && leftContainer) {
23
+ leftContainer.style.width = leftWidth;
24
+ console.log('[Resize] Loaded left panel width:', leftWidth);
25
+ }
26
+
27
+ if (rightWidth && rightContainer) {
28
+ rightContainer.style.width = rightWidth;
29
+ console.log('[Resize] Loaded right panel width:', rightWidth);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Save panel width to localStorage
35
+ */
36
+ function saveWidth(key, width) {
37
+ try {
38
+ localStorage.setItem(key, `${width}px`);
39
+ } catch (e) {
40
+ console.warn('[Resize] Failed to save width:', e);
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Initialize resize handler for left tool panel
46
+ */
47
+ function initLeftResizeHandler() {
4
48
  const toolPanelContainer = getById('tool-panel-container');
5
49
  const handle = getById('resize-handler');
6
50
 
@@ -38,6 +82,64 @@ export function initResizeHandler() {
38
82
  if (isResizing) {
39
83
  isResizing = false;
40
84
  document.body.classList.remove('resizing');
85
+
86
+ // Save width to localStorage
87
+ const finalWidth = toolPanelContainer.getBoundingClientRect().width;
88
+ saveWidth(STORAGE_KEY_LEFT_WIDTH, finalWidth);
89
+ }
90
+ });
91
+
92
+ console.log('[Resize] Left resize handler initialized');
93
+ }
94
+
95
+ /**
96
+ * Initialize resize handler for right tool panel
97
+ */
98
+ function initRightResizeHandler() {
99
+ const toolPanelContainerRight = getById('tool-panel-container-right');
100
+ const handleRight = getById('resize-handler-right');
101
+
102
+ if (!toolPanelContainerRight || !handleRight) {
103
+ return;
104
+ }
105
+
106
+ let isResizing = false;
107
+ let startX = 0;
108
+ let startWidth = 0;
109
+
110
+ handleRight.addEventListener('mousedown', (e) => {
111
+ isResizing = true;
112
+ startX = e.clientX;
113
+ startWidth = toolPanelContainerRight.getBoundingClientRect().width;
114
+
115
+ document.body.classList.add('resizing');
116
+ e.preventDefault();
117
+ });
118
+
119
+ document.addEventListener('mousemove', (e) => {
120
+ if (!isResizing) return;
121
+
122
+ requestAnimationFrame(() => {
123
+ const currentX = e.clientX;
124
+ // For right panel, dragging left (negative diff) should increase width
125
+ const diffX = startX - currentX; // Inverted direction
126
+ const newWidth = Math.max(250, Math.min(600, startWidth + diffX)); // Min 250px, Max 600px
127
+
128
+ // Update width of tool-panel-container-right
129
+ toolPanelContainerRight.style.width = `${newWidth}px`;
130
+ });
131
+ });
132
+
133
+ document.addEventListener('mouseup', () => {
134
+ if (isResizing) {
135
+ isResizing = false;
136
+ document.body.classList.remove('resizing');
137
+
138
+ // Save width to localStorage
139
+ const finalWidth = toolPanelContainerRight.getBoundingClientRect().width;
140
+ saveWidth(STORAGE_KEY_RIGHT_WIDTH, finalWidth);
41
141
  }
42
142
  });
143
+
144
+ console.log('[Resize] Right resize handler initialized');
43
145
  }
@@ -1,19 +1,25 @@
1
1
  import { getById, qsa } from '../utils.js';
2
+ import { toggleDashboard } from './keyboard-shortcuts.js';
2
3
 
3
4
  let activePanel = null;
5
+ let activePanelRight = null;
6
+
7
+ const STORAGE_KEY_ACTIVE_PANEL_LEFT = 'vg-coder-active-panel-left';
8
+ const STORAGE_KEY_ACTIVE_PANEL_RIGHT = 'vg-coder-active-panel-right';
4
9
 
5
10
  /**
6
11
  * Initialize Tool Window system
7
12
  */
8
13
  export function initToolWindow() {
14
+ // Initialize left tool window bar
9
15
  const toolWindowBar = getById('tool-window-bar');
10
16
  if (!toolWindowBar) {
11
17
  console.warn('[ToolWindow] Tool window bar not found');
12
18
  return;
13
19
  }
14
20
 
15
- // Attach event listeners to all tool window icons
16
- const icons = qsa('.tool-window-icon');
21
+ // Attach event listeners to all tool window icons (left side)
22
+ const icons = qsa('#tool-window-bar .tool-window-icon');
17
23
  icons.forEach(icon => {
18
24
  icon.addEventListener('click', () => {
19
25
  const panelId = icon.dataset.panel;
@@ -23,23 +29,69 @@ export function initToolWindow() {
23
29
  });
24
30
  });
25
31
 
26
- // Open Project panel by default after a short delay
27
- // This ensures all panel listeners are registered first
32
+ // Initialize right tool window bar
33
+ const toolWindowBarRight = getById('tool-window-bar-right');
34
+ if (toolWindowBarRight) {
35
+ const iconsRight = qsa('#tool-window-bar-right .tool-window-icon');
36
+ iconsRight.forEach(icon => {
37
+ icon.addEventListener('click', () => {
38
+ const panelId = icon.dataset.panel;
39
+ if (panelId) {
40
+ togglePanelRight(panelId);
41
+ }
42
+ });
43
+ });
44
+ console.log('[ToolWindow] Right tool window bar initialized');
45
+ }
46
+
47
+ // Initialize exit button
48
+ const exitBtn = getById('exit-dashboard-btn');
49
+ if (exitBtn) {
50
+ exitBtn.addEventListener('click', () => {
51
+ toggleDashboard();
52
+ console.log('[ToolWindow] Dashboard toggled via exit button');
53
+ });
54
+ console.log('[ToolWindow] Exit button initialized');
55
+ }
56
+
57
+ // Restore saved panel states after a short delay
28
58
  setTimeout(() => {
29
- togglePanel('project');
59
+ restorePanelStates();
30
60
  }, 100);
31
61
 
32
- console.log('[ToolWindow] Initialized with Project panel active');
62
+ console.log('[ToolWindow] Initialized');
63
+ }
64
+
65
+ /**
66
+ * Restore previously active panels from localStorage
67
+ */
68
+ function restorePanelStates() {
69
+ // Restore left panel
70
+ const savedLeftPanel = localStorage.getItem(STORAGE_KEY_ACTIVE_PANEL_LEFT);
71
+ if (savedLeftPanel) {
72
+ togglePanel(savedLeftPanel);
73
+ } else {
74
+ // Default to project panel if no saved state
75
+ togglePanel('project');
76
+ }
77
+
78
+ // Restore right panel
79
+ const savedRightPanel = localStorage.getItem(STORAGE_KEY_ACTIVE_PANEL_RIGHT);
80
+ if (savedRightPanel) {
81
+ togglePanelRight(savedRightPanel);
82
+ }
83
+
84
+ console.log('[ToolWindow] Restored panel states - Left:', savedLeftPanel || 'project', 'Right:', savedRightPanel || 'none');
33
85
  }
34
86
 
35
87
  /**
36
- * Toggle a specific panel
88
+ * Toggle a specific panel (left side)
37
89
  * @param {string} panelId - Panel ID to toggle (e.g., 'project', 'git')
38
90
  */
39
91
  export function togglePanel(panelId) {
40
92
  const panel = getById(`tool-panel-${panelId}`);
41
93
  const container = getById('tool-panel-container');
42
- const icon = qsa(`.tool-window-icon[data-panel="${panelId}"]`)[0];
94
+ const icon = qsa(`#tool-window-bar .tool-window-icon[data-panel="${panelId}"]`)[0];
43
95
 
44
96
  if (!panel || !container) {
45
97
  console.error('[ToolWindow] Panel or container not found:', panelId);
@@ -58,10 +110,22 @@ export function togglePanel(panelId) {
58
110
  // Open the new panel
59
111
  setActivePanel(panelId);
60
112
  container.classList.add('expanded');
113
+
114
+ // Restore saved width from localStorage (or use default)
115
+ const savedWidth = localStorage.getItem('vg-coder-left-panel-width');
116
+ if (savedWidth) {
117
+ container.style.width = savedWidth;
118
+ } else {
119
+ container.style.width = '520px'; // Default width
120
+ }
121
+
61
122
  panel.classList.add('active');
62
123
  if (icon) icon.classList.add('active');
63
124
 
64
125
  activePanel = panelId;
126
+
127
+ // Save active panel state to localStorage
128
+ localStorage.setItem(STORAGE_KEY_ACTIVE_PANEL_LEFT, panelId);
65
129
 
66
130
  // Trigger panel-specific initialization if needed
67
131
  triggerPanelInit(panelId);
@@ -70,15 +134,65 @@ export function togglePanel(panelId) {
70
134
  }
71
135
 
72
136
  /**
73
- * Close all open panels
137
+ * Toggle a specific panel (right side)
138
+ * @param {string} panelId - Panel ID to toggle (e.g., 'agent', 'browser')
139
+ */
140
+ export function togglePanelRight(panelId) {
141
+ const panel = getById(`tool-panel-${panelId}`);
142
+ const container = getById('tool-panel-container-right');
143
+ const icon = qsa(`#tool-window-bar-right .tool-window-icon[data-panel="${panelId}"]`)[0];
144
+
145
+ if (!panel || !container) {
146
+ console.error('[ToolWindow] Right panel or container not found:', panelId);
147
+ return;
148
+ }
149
+
150
+ // If clicking the same active panel, close it
151
+ if (activePanelRight === panelId) {
152
+ closeAllPanelsRight();
153
+ return;
154
+ }
155
+
156
+ // Close all right panels first
157
+ closeAllPanelsRight();
158
+
159
+ // Open the new panel
160
+ container.classList.add('expanded');
161
+
162
+ // Restore saved width from localStorage (or use default)
163
+ const savedWidth = localStorage.getItem('vg-coder-right-panel-width');
164
+ if (savedWidth) {
165
+ container.style.width = savedWidth;
166
+ } else {
167
+ container.style.width = '520px'; // Default width
168
+ }
169
+
170
+ panel.classList.add('active');
171
+ if (icon) icon.classList.add('active');
172
+
173
+ activePanelRight = panelId;
174
+
175
+ // Save active right panel state to localStorage
176
+ localStorage.setItem(STORAGE_KEY_ACTIVE_PANEL_RIGHT, panelId);
177
+
178
+ // Trigger panel-specific initialization if needed
179
+ triggerPanelInit(panelId, 'right');
180
+
181
+ console.log('[ToolWindow] Opened right panel:', panelId);
182
+ }
183
+
184
+ /**
185
+ * Close all open panels (left side)
74
186
  */
75
187
  export function closeAllPanels() {
76
188
  const container = getById('tool-panel-container');
77
- const panels = qsa('.tool-panel');
78
- const icons = qsa('.tool-window-icon');
189
+ const panels = qsa('#tool-panel-container .tool-panel');
190
+ const icons = qsa('#tool-window-bar .tool-window-icon');
79
191
 
80
192
  if (container) {
81
193
  container.classList.remove('expanded');
194
+ // Set width to 0 to collapse panel (saved width will be restored on open)
195
+ container.style.width = '0';
82
196
  }
83
197
 
84
198
  panels.forEach(panel => {
@@ -90,16 +204,52 @@ export function closeAllPanels() {
90
204
  });
91
205
 
92
206
  activePanel = null;
207
+
208
+ // Clear saved panel state
209
+ localStorage.removeItem(STORAGE_KEY_ACTIVE_PANEL_LEFT);
93
210
 
94
211
  console.log('[ToolWindow] Closed all panels');
95
212
  }
96
213
 
214
+
215
+ /**
216
+ * Close all open panels (right side)
217
+ */
218
+ export function closeAllPanelsRight() {
219
+ const container = getById('tool-panel-container-right');
220
+ const panels = qsa('#tool-panel-container-right .tool-panel');
221
+ const icons = qsa('#tool-window-bar-right .tool-window-icon');
222
+
223
+ if (container) {
224
+ container.classList.remove('expanded');
225
+ // Set width to 0 to collapse panel (saved width will be restored on open)
226
+ container.style.width = '0';
227
+ }
228
+
229
+ panels.forEach(panel => {
230
+ panel.classList.remove('active');
231
+ });
232
+
233
+ icons.forEach(icon => {
234
+ icon.classList.remove('active');
235
+ });
236
+
237
+ activePanelRight = null;
238
+
239
+ // Clear saved right panel state
240
+ localStorage.removeItem(STORAGE_KEY_ACTIVE_PANEL_RIGHT);
241
+
242
+ console.log('[ToolWindow] Closed all right panels');
243
+ }
244
+
245
+
97
246
  /**
98
247
  * Set a panel as active (internal use)
99
248
  * @param {string} panelId - Panel ID
100
249
  */
101
250
  function setActivePanel(panelId) {
102
- const panels = qsa('.tool-panel');
251
+ // Only select panels from left container to avoid affecting right panels
252
+ const panels = qsa('#tool-panel-container .tool-panel');
103
253
  panels.forEach(panel => {
104
254
  if (panel.id === `tool-panel-${panelId}`) {
105
255
  panel.classList.add('active');
@@ -109,14 +259,16 @@ function setActivePanel(panelId) {
109
259
  });
110
260
  }
111
261
 
262
+
112
263
  /**
113
264
  * Trigger initialization for panel-specific features
114
265
  * @param {string} panelId - Panel ID
266
+ * @param {string} side - 'left' or 'right'
115
267
  */
116
- function triggerPanelInit(panelId) {
268
+ function triggerPanelInit(panelId, side = 'left') {
117
269
  // Dispatch custom event that panel modules can listen to
118
270
  const event = new CustomEvent('tool-panel-opened', {
119
- detail: { panelId }
271
+ detail: { panelId, side }
120
272
  });
121
273
  document.dispatchEvent(event);
122
274
  }
@@ -129,6 +281,14 @@ export function getActivePanel() {
129
281
  return activePanel;
130
282
  }
131
283
 
284
+ /**
285
+ * Get the currently active right panel ID
286
+ * @returns {string|null} Active right panel ID or null
287
+ */
288
+ export function getActivePanelRight() {
289
+ return activePanelRight;
290
+ }
291
+
132
292
  /**
133
293
  * Register a callback for when a panel is closed
134
294
  * @param {Function} callback - Callback function
@@ -152,3 +312,5 @@ export function onPanelClose(callback) {
152
312
  // Expose to window for HTML onclick if needed
153
313
  window.toggleToolPanel = togglePanel;
154
314
  window.closeToolPanels = closeAllPanels;
315
+ window.toggleToolPanelRight = togglePanelRight;
316
+ window.closeToolPanelsRight = closeAllPanelsRight;
@@ -17,6 +17,8 @@ import { initToolWindow } from './features/tool-window.js';
17
17
  import { initProjectPanel } from './features/project-panel.js';
18
18
  import { initGitPanel } from './features/git-panel.js';
19
19
  import { initCommandsPanel } from './features/commands-panel.js';
20
+ import { initBrowserPanel } from './features/browser-panel.js';
21
+ import { initAgentPanel } from './features/agent-panel.js';
20
22
 
21
23
  export async function initMain() {
22
24
  console.log('VG Coder: Starting Main Logic...');
@@ -37,6 +39,8 @@ export async function initMain() {
37
39
  initProjectPanel();
38
40
  initGitPanel();
39
41
  initCommandsPanel();
42
+ initBrowserPanel();
43
+ initAgentPanel();
40
44
 
41
45
  initGitView();
42
46
  initTerminal();