vg-coder-cli 2.0.44 → 2.0.46

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vg-coder-cli",
3
- "version": "2.0.44",
3
+ "version": "2.0.46",
4
4
  "description": "🚀 CLI tool to analyze projects, concatenate source files, count tokens, and export HTML with syntax highlighting and copy functionality",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -176,6 +176,7 @@
176
176
  .agent-file-list {
177
177
  display: flex;
178
178
  flex-wrap: wrap;
179
+ gap: 8px;
179
180
  }
180
181
 
181
182
  .agent-file-badge {
@@ -185,21 +186,43 @@
185
186
  background: #3f3f46;
186
187
  padding: 4px 8px;
187
188
  border-radius: 4px;
188
- margin-right: 6px;
189
- margin-bottom: 4px;
190
189
  font-size: 11px;
191
190
  color: #e4e4e7;
191
+ max-width: 100%;
192
+ }
193
+
194
+ .agent-file-badge.has-preview {
195
+ padding: 4px;
196
+ gap: 8px;
197
+ }
198
+
199
+ .agent-file-preview {
200
+ width: 40px;
201
+ height: 40px;
202
+ object-fit: cover;
203
+ border-radius: 4px;
204
+ border: 1px solid #52525b;
205
+ flex-shrink: 0;
206
+ }
207
+
208
+ .agent-file-info {
209
+ display: flex;
210
+ flex-direction: column;
211
+ gap: 2px;
212
+ min-width: 0;
213
+ flex: 1;
192
214
  }
193
215
 
194
216
  .agent-file-name {
195
- max-width: 150px;
196
217
  overflow: hidden;
197
218
  text-overflow: ellipsis;
198
219
  white-space: nowrap;
220
+ max-width: 150px;
199
221
  }
200
222
 
201
223
  .agent-file-size {
202
224
  color: #a1a1aa;
225
+ font-size: 10px;
203
226
  }
204
227
 
205
228
  .agent-file-remove {
@@ -208,9 +231,16 @@
208
231
  color: #ef4444;
209
232
  cursor: pointer;
210
233
  font-weight: bold;
211
- padding: 0 2px;
212
- font-size: 14px;
234
+ padding: 0 4px;
235
+ font-size: 16px;
213
236
  line-height: 1;
237
+ flex-shrink: 0;
238
+ transition: all 0.2s;
239
+ }
240
+
241
+ .agent-file-remove:hover {
242
+ color: #dc2626;
243
+ transform: scale(1.2);
214
244
  }
215
245
 
216
246
  /* Textarea */
@@ -324,17 +354,172 @@
324
354
  /* Mermaid Diagrams */
325
355
  .agent-mermaid {
326
356
  margin: 16px 0;
327
- padding: 20px;
328
357
  background-color: var(--code-block-bg, #161b22);
329
358
  border-radius: 6px;
359
+ overflow: hidden;
360
+ min-height: 100px;
361
+ position: relative;
362
+ }
363
+
364
+ .agent-mermaid-toolbar {
365
+ display: flex;
366
+ justify-content: flex-end;
367
+ gap: 4px;
368
+ padding: 8px 12px;
369
+ background: rgba(0, 0, 0, 0.3);
370
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
371
+ }
372
+
373
+ .agent-mermaid-btn {
374
+ display: inline-flex;
375
+ align-items: center;
376
+ gap: 4px;
377
+ padding: 4px 8px;
378
+ background: rgba(255, 255, 255, 0.1);
379
+ border: none;
380
+ border-radius: 4px;
381
+ color: #a1a1aa;
382
+ cursor: pointer;
383
+ font-size: 11px;
384
+ transition: all 0.2s ease;
385
+ }
386
+
387
+ .agent-mermaid-btn:hover {
388
+ background: rgba(255, 255, 255, 0.2);
389
+ color: #ededed;
390
+ }
391
+
392
+ .agent-mermaid-btn:active {
393
+ transform: scale(0.95);
394
+ }
395
+
396
+ .agent-mermaid-diagram {
397
+ padding: 20px;
330
398
  display: flex;
331
399
  justify-content: center;
332
400
  align-items: center;
333
401
  overflow-x: auto;
334
- min-height: 100px;
335
402
  }
336
403
 
337
- .agent-mermaid svg {
404
+ .agent-mermaid-diagram svg {
405
+ max-width: 100%;
406
+ height: auto;
407
+ }
408
+
409
+ /* Mermaid Toast Notification */
410
+ .agent-mermaid-toast {
411
+ position: absolute;
412
+ top: 50%;
413
+ left: 50%;
414
+ transform: translate(-50%, -50%);
415
+ padding: 8px 16px;
416
+ border-radius: 6px;
417
+ font-size: 12px;
418
+ font-weight: 500;
419
+ z-index: 100;
420
+ animation: mermaid-toast-fade 2s ease-out forwards;
421
+ }
422
+
423
+ .agent-mermaid-toast.success {
424
+ background: rgba(74, 222, 128, 0.9);
425
+ color: #000;
426
+ }
427
+
428
+ .agent-mermaid-toast.error {
429
+ background: rgba(239, 68, 68, 0.9);
430
+ color: #fff;
431
+ }
432
+
433
+ @keyframes mermaid-toast-fade {
434
+ 0% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
435
+ 15% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
436
+ 85% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
437
+ 100% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
438
+ }
439
+
440
+ /* Mermaid Fullscreen Modal */
441
+ .agent-mermaid-modal {
442
+ position: fixed;
443
+ top: 0;
444
+ left: 0;
445
+ right: 0;
446
+ bottom: 0;
447
+ background: rgba(0, 0, 0, 0.85);
448
+ z-index: 10000;
449
+ display: flex;
450
+ align-items: center;
451
+ justify-content: center;
452
+ padding: 40px;
453
+ opacity: 0;
454
+ transition: opacity 0.2s ease;
455
+ }
456
+
457
+ .agent-mermaid-modal.open {
458
+ opacity: 1;
459
+ }
460
+
461
+ .agent-mermaid-modal.closing {
462
+ opacity: 0;
463
+ }
464
+
465
+ .agent-mermaid-modal-content {
466
+ background: #1a1a1a;
467
+ border-radius: 12px;
468
+ max-width: 95vw;
469
+ max-height: 90vh;
470
+ overflow: hidden;
471
+ display: flex;
472
+ flex-direction: column;
473
+ box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5);
474
+ transform: scale(0.95);
475
+ transition: transform 0.2s ease;
476
+ }
477
+
478
+ .agent-mermaid-modal.open .agent-mermaid-modal-content {
479
+ transform: scale(1);
480
+ }
481
+
482
+ .agent-mermaid-modal-header {
483
+ display: flex;
484
+ justify-content: space-between;
485
+ align-items: center;
486
+ padding: 16px 20px;
487
+ background: #252525;
488
+ border-bottom: 1px solid #333;
489
+ color: #ededed;
490
+ font-weight: 600;
491
+ font-size: 14px;
492
+ }
493
+
494
+ .agent-mermaid-modal-actions {
495
+ display: flex;
496
+ gap: 8px;
497
+ }
498
+
499
+ .agent-mermaid-modal-actions .agent-mermaid-btn {
500
+ padding: 6px 12px;
501
+ }
502
+
503
+ .agent-mermaid-close {
504
+ background: rgba(239, 68, 68, 0.2);
505
+ color: #ef4444;
506
+ }
507
+
508
+ .agent-mermaid-close:hover {
509
+ background: rgba(239, 68, 68, 0.3);
510
+ color: #f87171;
511
+ }
512
+
513
+ .agent-mermaid-modal-body {
514
+ padding: 40px;
515
+ overflow: auto;
516
+ display: flex;
517
+ align-items: center;
518
+ justify-content: center;
519
+ background: #161b22;
520
+ }
521
+
522
+ .agent-mermaid-modal-body svg {
338
523
  max-width: 100%;
339
524
  height: auto;
340
525
  }
@@ -245,17 +245,172 @@
245
245
  /* Mermaid Diagrams */
246
246
  .markdown-body .mermaid-diagram {
247
247
  margin: 16px 0;
248
- padding: 20px;
249
248
  background-color: var(--code-block-bg, #161b22);
250
249
  border-radius: 6px;
250
+ overflow: hidden;
251
+ min-height: 100px;
252
+ position: relative;
253
+ }
254
+
255
+ .mermaid-toolbar {
256
+ display: flex;
257
+ justify-content: flex-end;
258
+ gap: 4px;
259
+ padding: 8px 12px;
260
+ background: rgba(0, 0, 0, 0.3);
261
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
262
+ }
263
+
264
+ .mermaid-btn {
265
+ display: inline-flex;
266
+ align-items: center;
267
+ gap: 4px;
268
+ padding: 4px 8px;
269
+ background: rgba(255, 255, 255, 0.1);
270
+ border: none;
271
+ border-radius: 4px;
272
+ color: #a1a1aa;
273
+ cursor: pointer;
274
+ font-size: 11px;
275
+ transition: all 0.2s ease;
276
+ }
277
+
278
+ .mermaid-btn:hover {
279
+ background: rgba(255, 255, 255, 0.2);
280
+ color: #ededed;
281
+ }
282
+
283
+ .mermaid-btn:active {
284
+ transform: scale(0.95);
285
+ }
286
+
287
+ .mermaid-diagram-content {
288
+ padding: 20px;
251
289
  display: flex;
252
290
  justify-content: center;
253
291
  align-items: center;
254
292
  overflow-x: auto;
255
- min-height: 100px;
256
293
  }
257
294
 
258
- .markdown-body .mermaid-diagram svg {
295
+ .mermaid-diagram-content svg {
296
+ max-width: 100%;
297
+ height: auto;
298
+ }
299
+
300
+ /* Mermaid Toast Notification */
301
+ .mermaid-toast {
302
+ position: absolute;
303
+ top: 50%;
304
+ left: 50%;
305
+ transform: translate(-50%, -50%);
306
+ padding: 8px 16px;
307
+ border-radius: 6px;
308
+ font-size: 12px;
309
+ font-weight: 500;
310
+ z-index: 100;
311
+ animation: mermaid-toast-fade 2s ease-out forwards;
312
+ }
313
+
314
+ .mermaid-toast.success {
315
+ background: rgba(74, 222, 128, 0.9);
316
+ color: #000;
317
+ }
318
+
319
+ .mermaid-toast.error {
320
+ background: rgba(239, 68, 68, 0.9);
321
+ color: #fff;
322
+ }
323
+
324
+ @keyframes mermaid-toast-fade {
325
+ 0% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
326
+ 15% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
327
+ 85% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
328
+ 100% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
329
+ }
330
+
331
+ /* Mermaid Fullscreen Modal */
332
+ .mermaid-modal {
333
+ position: fixed;
334
+ top: 0;
335
+ left: 0;
336
+ right: 0;
337
+ bottom: 0;
338
+ background: rgba(0, 0, 0, 0.85);
339
+ z-index: 10000;
340
+ display: flex;
341
+ align-items: center;
342
+ justify-content: center;
343
+ padding: 40px;
344
+ opacity: 0;
345
+ transition: opacity 0.2s ease;
346
+ }
347
+
348
+ .mermaid-modal.open {
349
+ opacity: 1;
350
+ }
351
+
352
+ .mermaid-modal.closing {
353
+ opacity: 0;
354
+ }
355
+
356
+ .mermaid-modal-content {
357
+ background: #1a1a1a;
358
+ border-radius: 12px;
359
+ max-width: 95vw;
360
+ max-height: 90vh;
361
+ overflow: hidden;
362
+ display: flex;
363
+ flex-direction: column;
364
+ box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5);
365
+ transform: scale(0.95);
366
+ transition: transform 0.2s ease;
367
+ }
368
+
369
+ .mermaid-modal.open .mermaid-modal-content {
370
+ transform: scale(1);
371
+ }
372
+
373
+ .mermaid-modal-header {
374
+ display: flex;
375
+ justify-content: space-between;
376
+ align-items: center;
377
+ padding: 16px 20px;
378
+ background: #252525;
379
+ border-bottom: 1px solid #333;
380
+ color: #ededed;
381
+ font-weight: 600;
382
+ font-size: 14px;
383
+ }
384
+
385
+ .mermaid-modal-actions {
386
+ display: flex;
387
+ gap: 8px;
388
+ }
389
+
390
+ .mermaid-modal-actions .mermaid-btn {
391
+ padding: 6px 12px;
392
+ }
393
+
394
+ .mermaid-close {
395
+ background: rgba(239, 68, 68, 0.2);
396
+ color: #ef4444;
397
+ }
398
+
399
+ .mermaid-close:hover {
400
+ background: rgba(239, 68, 68, 0.3);
401
+ color: #f87171;
402
+ }
403
+
404
+ .mermaid-modal-body {
405
+ padding: 40px;
406
+ overflow: auto;
407
+ display: flex;
408
+ align-items: center;
409
+ justify-content: center;
410
+ background: #161b22;
411
+ }
412
+
413
+ .mermaid-modal-body svg {
259
414
  max-width: 100%;
260
415
  height: auto;
261
416
  }
@@ -7,6 +7,8 @@ import { getById } from '../utils.js';
7
7
  // Import markdown-it and mermaid from npm packages (bundled by webpack)
8
8
  import markdownit from 'markdown-it';
9
9
  import mermaid from 'mermaid';
10
+ // Import mermaid viewer for fullscreen functionality
11
+ import { createMermaidToolbar, openMermaidViewer, showToast as showMermaidToast } from './mermaid-viewer.js';
10
12
 
11
13
  // State
12
14
  let messages = [];
@@ -159,6 +161,46 @@ function attachEventListeners() {
159
161
  this.style.height = Math.min(this.scrollHeight, 120) + 'px';
160
162
  }
161
163
  });
164
+
165
+ // Paste event - Handle images from clipboard
166
+ input.addEventListener('paste', async (e) => {
167
+ if (isProcessing) return;
168
+
169
+ const items = e.clipboardData?.items;
170
+ if (!items) return;
171
+
172
+ // Check for image items
173
+ const imageItems = Array.from(items).filter(item =>
174
+ item.type.startsWith('image/')
175
+ );
176
+
177
+ if (imageItems.length === 0) return;
178
+
179
+ // Prevent default paste for images
180
+ e.preventDefault();
181
+
182
+ // Process all images
183
+ for (const item of imageItems) {
184
+ const blob = item.getAsFile();
185
+ if (!blob) continue;
186
+
187
+ // Create a File object with a proper name
188
+ const timestamp = Date.now();
189
+ const extension = blob.type.split('/')[1] || 'png';
190
+ const file = new File(
191
+ [blob],
192
+ `pasted-image-${timestamp}.${extension}`,
193
+ { type: blob.type }
194
+ );
195
+
196
+ // Add to selected files
197
+ selectedFiles.push(file);
198
+ console.log('[AgentPanel] Image pasted:', file.name, file.type, `${(file.size/1024).toFixed(1)}KB`);
199
+ }
200
+
201
+ // Update UI to show pasted images
202
+ renderFileList();
203
+ });
162
204
  }
163
205
 
164
206
  // File button
@@ -433,17 +475,29 @@ async function processMermaidDiagrams(container) {
433
475
  const id = `agent-mermaid-${Date.now()}-${i}`;
434
476
  const { svg, bindFunctions } = await mermaid.render(id, code);
435
477
 
436
- // Create wrapper div for mermaid
478
+ // Create wrapper div for mermaid with toolbar
437
479
  const wrapper = document.createElement('div');
438
480
  wrapper.className = 'agent-mermaid';
439
- wrapper.innerHTML = svg;
481
+ wrapper.style.cssText = 'position: relative; margin: 16px 0; background: #161b22; border-radius: 6px; overflow: hidden;';
482
+
483
+ // Create toolbar using mermaid-viewer module
484
+ const toolbar = createMermaidToolbar(code, svg);
485
+
486
+ // Create diagram container
487
+ const diagramContainer = document.createElement('div');
488
+ diagramContainer.className = 'agent-mermaid-diagram';
489
+ diagramContainer.style.cssText = 'padding: 20px; display: flex; justify-content: center; align-items: center; overflow-x: auto;';
490
+ diagramContainer.innerHTML = svg;
491
+
492
+ wrapper.appendChild(toolbar);
493
+ wrapper.appendChild(diagramContainer);
440
494
 
441
495
  // Replace pre/code with wrapper
442
496
  preElement.replaceWith(wrapper);
443
497
 
444
498
  // Bind any interactive functions if present
445
499
  if (bindFunctions) {
446
- bindFunctions(wrapper);
500
+ bindFunctions(diagramContainer);
447
501
  }
448
502
 
449
503
  console.log(`[AgentPanel] Rendered mermaid diagram ${i + 1}`);
@@ -625,13 +679,21 @@ function renderFileList() {
625
679
  const listContainer = getById('agent-file-list');
626
680
  if (!listContainer) return;
627
681
 
628
- listContainer.innerHTML = selectedFiles.map((file, index) => `
629
- <div class="agent-file-badge">
630
- <span class="agent-file-name">📎 ${file.name}</span>
631
- <span class="agent-file-size">(${(file.size / 1024).toFixed(0)}KB)</span>
632
- <button class="agent-file-remove" onclick="window.removeAgentFile(${index})">×</button>
633
- </div>
634
- `).join('');
682
+ listContainer.innerHTML = selectedFiles.map((file, index) => {
683
+ const isImage = file.type.startsWith('image/');
684
+ const fileUrl = isImage ? URL.createObjectURL(file) : '';
685
+
686
+ return `
687
+ <div class="agent-file-badge ${isImage ? 'has-preview' : ''}">
688
+ ${isImage ? `<img class="agent-file-preview" src="${fileUrl}" alt="${file.name}" />` : '📎'}
689
+ <div class="agent-file-info">
690
+ <span class="agent-file-name">${file.name}</span>
691
+ <span class="agent-file-size">(${(file.size / 1024).toFixed(0)}KB)</span>
692
+ </div>
693
+ <button class="agent-file-remove" onclick="window.removeAgentFile(${index})">×</button>
694
+ </div>
695
+ `;
696
+ }).join('');
635
697
  }
636
698
 
637
699
  /**
@@ -708,3 +770,4 @@ function escapeHtml(text) {
708
770
  div.textContent = text;
709
771
  return div.innerHTML;
710
772
  }
773
+
@@ -6,6 +6,8 @@ import hljs from 'highlight.js/lib/core';
6
6
  import markdownit from 'markdown-it';
7
7
  // Import mermaid for rendering diagrams
8
8
  import mermaid from 'mermaid';
9
+ // Import mermaid viewer for fullscreen functionality
10
+ import { createMermaidToolbar, openMermaidViewer, showToast as showMermaidToast } from './mermaid-viewer.js';
9
11
 
10
12
  // Import common languages to reduce bundle size
11
13
  import javascript from 'highlight.js/lib/languages/javascript';
@@ -80,17 +82,29 @@ async function renderMermaidDiagrams(container) {
80
82
  const id = `mermaid-diagram-${Date.now()}-${i}`;
81
83
  const { svg, bindFunctions } = await mermaid.render(id, code);
82
84
 
83
- // Create wrapper div for mermaid
85
+ // Create wrapper div for mermaid with toolbar
84
86
  const wrapper = document.createElement('div');
85
87
  wrapper.className = 'mermaid-diagram';
86
- wrapper.innerHTML = svg;
88
+ wrapper.style.cssText = 'position: relative; margin: 16px 0; background: #161b22; border-radius: 6px; overflow: hidden;';
89
+
90
+ // Create toolbar using mermaid-viewer module
91
+ const toolbar = createMermaidToolbar(code, svg);
92
+
93
+ // Create diagram container
94
+ const diagramContainer = document.createElement('div');
95
+ diagramContainer.className = 'mermaid-diagram-content';
96
+ diagramContainer.style.cssText = 'padding: 20px; display: flex; justify-content: center; align-items: center; overflow-x: auto;';
97
+ diagramContainer.innerHTML = svg;
98
+
99
+ wrapper.appendChild(toolbar);
100
+ wrapper.appendChild(diagramContainer);
87
101
 
88
102
  // Replace pre/code with wrapper
89
103
  pre.replaceWith(wrapper);
90
104
 
91
105
  // Bind any interactive functions if present
92
106
  if (bindFunctions) {
93
- bindFunctions(wrapper);
107
+ bindFunctions(diagramContainer);
94
108
  }
95
109
 
96
110
  console.log(`[Mermaid] Successfully rendered diagram ${i + 1}`);
@@ -184,3 +198,4 @@ function escapeHtml(text) {
184
198
  .replace(/"/g, "&quot;")
185
199
  .replace(/'/g, "&#039;");
186
200
  }
201
+