vidpipe 1.3.23 → 1.3.25

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.
@@ -150,8 +150,8 @@
150
150
 
151
151
  function getGroupPlatforms(group) {
152
152
  return [...new Set(group.items.map(item => {
153
- const platform = normalizePlatform(item.metadata.platform)
154
- return PLATFORMS[platform]?.name || item.metadata.platform
153
+ const platform = normalizePlatform(item.platform)
154
+ return PLATFORMS[platform]?.name || item.platform
155
155
  }))]
156
156
  }
157
157
 
@@ -238,6 +238,7 @@
238
238
  <div class="flex items-center gap-2 text-xs text-gray-500" aria-label="Keyboard shortcuts">
239
239
  <kbd class="px-1.5 py-0.5 bg-white/5 rounded border border-white/10">←</kbd> Reject
240
240
  <kbd class="px-1.5 py-0.5 bg-white/5 rounded border border-white/10">→</kbd> Approve
241
+ <kbd class="px-1.5 py-0.5 bg-yellow-500/10 rounded border border-yellow-500/30 text-yellow-400">↑</kbd> <span class="text-yellow-400">Priority</span>
241
242
  <kbd class="px-1.5 py-0.5 bg-white/5 rounded border border-white/10">Space</kbd> Skip
242
243
  </div>
243
244
  </div>
@@ -348,7 +349,7 @@
348
349
 
349
350
  const mediaType = group.mediaType || 'video'
350
351
  const mediaExt = mediaType === 'image' ? 'png' : 'mp4'
351
- const mediaUrl = `/media/queue/${encodeURIComponent(firstItem.id)}/media.${mediaExt}`
352
+ const mediaUrl = firstItem.mediaUrl || `/api/media/${encodeURIComponent(firstItem.id)}/media.${mediaExt}`
352
353
 
353
354
  if (mediaType === 'image') {
354
355
  return html`
@@ -382,7 +383,7 @@
382
383
  function ThumbnailPreview({ group }) {
383
384
  const firstItem = group.items[0]
384
385
  if (!firstItem) return null
385
- const thumbnailUrl = '/media/queue/' + encodeURIComponent(firstItem.id) + '/thumbnail.png'
386
+ const thumbnailUrl = firstItem.thumbnailUrl || '/api/media/' + encodeURIComponent(firstItem.id) + '/thumbnail.png'
386
387
  const [loaded, setLoaded] = useState(false)
387
388
  const [error, setError] = useState(false)
388
389
 
@@ -411,7 +412,7 @@
411
412
  <div class="text-xs font-semibold text-gray-400 mb-2">Select platforms to publish:</div>
412
413
  <div class="flex flex-wrap gap-2">
413
414
  ${group.items.map(item => {
414
- const platform = normalizePlatform(item.metadata.platform)
415
+ const platform = normalizePlatform(item.platform)
415
416
  const cfg = PLATFORMS[platform] || { icon: '❓', color: '#888', name: platform }
416
417
  const isSelected = selectedPlatforms.includes(item.id)
417
418
  const connAcct = accounts[platform]
@@ -454,7 +455,7 @@
454
455
  <div class="text-xs font-semibold text-gray-400 mb-2">📝 Posts per platform:</div>
455
456
  <div class="space-y-3">
456
457
  ${group.items.map(item => {
457
- const platform = normalizePlatform(item.metadata.platform)
458
+ const platform = normalizePlatform(item.platform)
458
459
  const cfg = PLATFORMS[platform] || { icon: '❓', color: '#888', name: platform }
459
460
  const content = item.postContent || ''
460
461
  return html`
@@ -482,7 +483,7 @@
482
483
  </div>`
483
484
  }
484
485
 
485
- function ActionButtons({ onReject, onSkip, onApprove, selectedCount }) {
486
+ function ActionButtons({ onReject, onSkip, onApprove, onPriority, selectedCount }) {
486
487
  const approveDisabled = selectedCount === 0
487
488
  return html`
488
489
  <div class="px-5 py-4 flex items-center justify-center gap-3">
@@ -512,10 +513,22 @@
512
513
  >
513
514
  <span>✅</span> Approve ${selectedCount > 0 ? `(${selectedCount})` : ''}
514
515
  </button>
516
+ <button
517
+ onClick=${onPriority}
518
+ class="action-btn flex items-center gap-2 px-5 py-2.5 rounded-xl text-sm font-medium border ${
519
+ approveDisabled
520
+ ? 'bg-gray-500/10 text-gray-500 border-gray-500/20 cursor-not-allowed opacity-50'
521
+ : 'bg-yellow-500/10 hover:bg-yellow-500/20 text-yellow-400 border-yellow-500/30'
522
+ }"
523
+ title="Priority approve — jumps to front of queue (↑)"
524
+ disabled=${approveDisabled}
525
+ >
526
+ <span>⚡</span> Priority
527
+ </button>
515
528
  </div>`
516
529
  }
517
530
 
518
- function GroupedPostCard({ group, accounts, selectedPlatforms, onTogglePlatform, animClass, onReject, onSkip, onApprove }) {
531
+ function GroupedPostCard({ group, accounts, selectedPlatforms, onTogglePlatform, animClass, onReject, onSkip, onApprove, onPriority }) {
519
532
  const selectedCount = selectedPlatforms.length
520
533
  const groupTitle = getGroupTitle(group)
521
534
  const groupPlatforms = getGroupPlatforms(group)
@@ -553,6 +566,7 @@
553
566
  onReject=${onReject}
554
567
  onSkip=${onSkip}
555
568
  onApprove=${onApprove}
569
+ onPriority=${onPriority}
556
570
  selectedCount=${selectedCount}
557
571
  />
558
572
  </div>
@@ -624,7 +638,7 @@
624
638
  if (currentGroup) {
625
639
  const availableIds = currentGroup.items
626
640
  .filter(item => {
627
- const platform = normalizePlatform(item.metadata.platform)
641
+ const platform = normalizePlatform(item.platform)
628
642
  return !!accounts[platform]
629
643
  })
630
644
  .map(item => item.id)
@@ -648,7 +662,7 @@
648
662
  }, 250)
649
663
  }, [])
650
664
 
651
- const approveGroup = useCallback(async () => {
665
+ const approveGroup = useCallback(async (priority = false) => {
652
666
  if (busy || !currentGroup || selectedPlatforms.length === 0) return
653
667
 
654
668
  const count = selectedPlatforms.length
@@ -658,11 +672,11 @@
658
672
  fetch('/api/posts/bulk-approve', {
659
673
  method: 'POST',
660
674
  headers: { 'Content-Type': 'application/json' },
661
- body: JSON.stringify({ itemIds: selectedPlatforms }),
675
+ body: JSON.stringify({ itemIds: selectedPlatforms, priority }),
662
676
  }).catch(err => showToast(`Approve failed: ${err.message}`, 'error'))
663
677
 
664
678
  setStats(s => ({ ...s, approved: s.approved + count }))
665
- showToast(`Scheduling ${count} post(s)…`, 'success')
679
+ showToast(priority ? `⚡ Priority scheduling ${count} post(s)…` : `Scheduling ${count} post(s)…`, 'success')
666
680
 
667
681
  animateOut(() => {
668
682
  setAllGroups(prev => prev.filter(g => g.groupKey !== groupKey))
@@ -706,7 +720,8 @@
706
720
  if (busy) return
707
721
  switch (e.key) {
708
722
  case 'ArrowLeft': e.preventDefault(); rejectGroup(); break
709
- case 'ArrowRight': e.preventDefault(); approveGroup(); break
723
+ case 'ArrowRight': e.preventDefault(); approveGroup(false); break
724
+ case 'ArrowUp': e.preventDefault(); approveGroup(true); break
710
725
  case ' ': e.preventDefault(); skipGroup(); break
711
726
  }
712
727
  }
@@ -732,7 +747,8 @@
732
747
  animClass=${animClass}
733
748
  onReject=${rejectGroup}
734
749
  onSkip=${skipGroup}
735
- onApprove=${approveGroup}
750
+ onApprove=${() => approveGroup(false)}
751
+ onPriority=${() => approveGroup(true)}
736
752
  />`
737
753
  }
738
754
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vidpipe",
3
- "version": "1.3.23",
3
+ "version": "1.3.25",
4
4
  "description": "AI-powered pipeline that watches for video recordings and generates transcripts, summaries, short clips, and social media posts",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -63,6 +63,8 @@
63
63
  "type": "module",
64
64
  "dependencies": {
65
65
  "@anthropic-ai/sdk": "^0.74.0",
66
+ "@azure/data-tables": "^13.3.2",
67
+ "@azure/storage-blob": "^12.31.0",
66
68
  "@ffprobe-installer/ffprobe": "^2.1.2",
67
69
  "@github/copilot-sdk": "^0.2.0",
68
70
  "@google/genai": "^1.41.0",
@@ -71,7 +73,7 @@
71
73
  "dotenv": "^17.2.4",
72
74
  "express": "^5.2.1",
73
75
  "fluent-ffmpeg": "^2.1.3",
74
- "ink": "^6.8.0",
76
+ "ink": "^7.0.1",
75
77
  "ink-text-input": "^6.0.0",
76
78
  "octokit": "^5.0.5",
77
79
  "onnxruntime-node": "^1.24.1",