feat: complete release preparation, 10+ ad mediation, CI/CD, and docker deployment
Some checks failed
CI Pipeline / Code Quality & Typecheck (push) Waiting to run
CI Pipeline / Test Suite (macos-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (ubuntu-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (windows-latest) (push) Blocked by required conditions
CI Pipeline / Build Validation (admin) (push) Blocked by required conditions
CI Pipeline / Build Validation (desktop) (push) Blocked by required conditions
Deploy Landing Page / deploy (push) Blocked by required conditions
Deploy Landing Page / build (push) Waiting to run
Release & Packaging Pipeline / Build & Publish Admin Docker Image (push) Failing after 8s
Release & Code Signing CA Pipeline / build-and-sign-windows (push) Failing after 1m51s
Build macOS / Build & Package (macOS) (push) Failing after 4s
Build macOS / Build & Package (macOS)-1 (push) Failing after 5s
Release & Code Signing CA Pipeline / build-and-sign-macos (push) Failing after 3s
Release & Packaging Pipeline / Package macOS Desktop App (push) Failing after 4s
Release & Packaging Pipeline / Package Windows Desktop App (push) Failing after 2m28s
Release & Packaging Pipeline / Publish Official GitHub Release (push) Has been skipped

This commit is contained in:
Yun Chan 2026-08-20 11:12:05 +09:00
parent 5cd1de6859
commit 708e20f747
406 changed files with 42464 additions and 6199 deletions

View file

@ -0,0 +1,385 @@
// apps/admin/src/app/(admin)/pipelines/page.tsx
// D3RO Voice — AI & Voice Pipeline Intelligence Console (Phase 1~15.5 SSOT)
import { Box, Typography, Button } from '@mui/material'
import { fetchServerStats } from '@/lib/api-server'
import { C, FONT_SANS, FONT_MONO, panelSx, statusBadgeSx } from '@/lib/console-theme'
import { StatRing, TactileBadge, DoubleBezelCard } from '@d3ro/ui/components/ds'
export default async function PipelinesPage(): Promise<React.ReactElement> {
const stats = await fetchServerStats()
const { whisper, ollama, realtimeVoice, ragVector, meetingIntelligence } = stats.pipelines
return (
<>
{/* Header Bar */}
<Box
sx={{
...panelSx,
minHeight: 76,
px: { xs: 2.5, md: 4 },
py: 2,
display: 'flex',
flexWrap: 'wrap',
alignItems: 'center',
justifyContent: 'space-between',
gap: 2,
}}
>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<Box
sx={{
width: 4,
height: 28,
borderRadius: '999px',
background: 'linear-gradient(180deg, #06b6d4 0%, #3b82f6 100%)',
}}
/>
<Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
<Typography
component="h1"
sx={{
fontFamily: FONT_SANS,
fontSize: '18px',
fontWeight: 700,
color: C.bright,
letterSpacing: '-0.02em',
m: 0,
}}
>
AI & Voice Pipeline Matrix
</Typography>
<TactileBadge ledColor="green" ledPulse tone="success" mono>
ORCHESTRATOR ONLINE
</TactileBadge>
</Box>
<Typography
sx={{
fontFamily: FONT_MONO,
fontSize: '11px',
color: C.dim,
letterSpacing: '0.04em',
mt: 0.25,
}}
>
LOCAL WHISPER OLLAMA V0.32.1 GPT-REALTIME 2.1 VECTOR RAG DIARIZATION
</Typography>
</Box>
</Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
<Button
variant="outlined"
size="small"
sx={{
fontFamily: FONT_SANS,
fontSize: '12px',
color: C.bright,
borderColor: C.borderHl,
bgcolor: 'rgba(17, 26, 48, 0.6)',
borderRadius: '10px',
textTransform: 'none',
px: 2,
'&:hover': { borderColor: C.accentLight, bgcolor: 'rgba(26, 38, 68, 0.8)' },
}}
>
Run Diagnostic Ping
</Button>
</Box>
</Box>
{/* Main Grid: 5 Core Pipeline Domains */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
{/* Top Split: Whisper STT & Ollama LLM */}
<Box sx={{ display: 'grid', gridTemplateColumns: { xs: '1fr', lg: '1fr 1fr' }, gap: 3 }}>
{/* Whisper STT Card */}
<DoubleBezelCard interactive bezelPadding="6px" innerPadding="24px">
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<StatRing color="blue" size={48}>
<svg width="22" height="22" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 100-6 3 3 0 000 6z" />
</svg>
</StatRing>
<Box>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '16px', fontWeight: 700, color: C.bright }}>
Faster-Whisper STT Sidecar
</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '11px', color: C.cyanLight }}>
{whisper.activeModel}
</Typography>
</Box>
</Box>
<Box component="span" sx={statusBadgeSx('blue')}>
DEFAULT STT
</Box>
</Box>
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 1.5, mb: 2.5 }}>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>AVG LATENCY</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.bright }}>
{whisper.avgLatencyMs}ms
</Typography>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>SPEEDUP FACTOR</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.green400 }}>
{whisper.speedupFactor}
</Typography>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>GPU VRAM</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.cyanLight }}>
{whisper.gpuVramUsage}
</Typography>
</Box>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.5)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '12px', color: C.text, lineHeight: 1.6 }}>
<strong>Dual-Condition Flush:</strong> Audio buffer flushes parallel with model warm-up.<br />
<strong>Realtime Streaming:</strong> {whisper.partialStreamingFps} fps interim partial transcription in RecordingTip popup.<br />
<strong>Total Today:</strong> {whisper.totalTranscriptionsToday.toLocaleString()} voice transcriptions processed.
</Typography>
</Box>
</DoubleBezelCard>
{/* Bundled Ollama LLM Card */}
<DoubleBezelCard interactive bezelPadding="6px" innerPadding="24px">
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<StatRing color="purple" size={48}>
<svg width="22" height="22" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</StatRing>
<Box>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '16px', fontWeight: 700, color: C.bright }}>
Bundled Ollama Runtime
</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '11px', color: C.purple400 }}>
{ollama.version} (119MB Pruned)
</Typography>
</Box>
</Box>
<Box component="span" sx={statusBadgeSx('purple')}>
LOCAL LLM
</Box>
</Box>
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 1.5, mb: 2.5 }}>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>THROUGHPUT</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.bright }}>
{ollama.tokensPerSecond} tok/s
</Typography>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>CONTEXT LIMIT</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.cyanLight }}>
{ollama.activeContextLimit}
</Typography>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>VRAM OCCUPANCY</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.purple400 }}>
{ollama.vramAllocated}
</Typography>
</Box>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.5)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '12px', color: C.text, lineHeight: 1.6 }}>
<strong>Loaded Models:</strong> {ollama.loadedModels.join(', ')}<br />
<strong>NDJSON Streaming:</strong> Zero-latency token streaming for Auto Polish & AI Chat.<br />
<strong>Active Local Sessions:</strong> {ollama.activeSessions} concurrent local inference threads.
</Typography>
</Box>
</DoubleBezelCard>
</Box>
{/* Middle Split: Realtime Live Voice & Vector RAG */}
<Box sx={{ display: 'grid', gridTemplateColumns: { xs: '1fr', lg: '1fr 1fr' }, gap: 3 }}>
{/* GPT-Realtime 2.1 Voice Engine */}
<DoubleBezelCard interactive bezelPadding="6px" innerPadding="24px">
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<StatRing color="orange" size={48}>
<svg width="22" height="22" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
</StatRing>
<Box>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '16px', fontWeight: 700, color: C.bright }}>
GPT-Realtime 2.1 Live Engine
</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '11px', color: C.orange400 }}>
{realtimeVoice.backend}
</Typography>
</Box>
</Box>
<Box component="span" sx={statusBadgeSx('orange')}>
PRO+ PREMIUM
</Box>
</Box>
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 1.5, mb: 2.5 }}>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>LIVE STREAMS</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.orange400 }}>
{realtimeVoice.activeStreams} Active
</Typography>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>AUDIO RTT</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.bright }}>
{realtimeVoice.avgAudioRttMs}ms
</Typography>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>LOCAL FALLBACK</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.green400 }}>
{realtimeVoice.localFallbackRate}
</Typography>
</Box>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.5)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '12px', color: C.text, lineHeight: 1.6 }}>
<strong>Ultra-low Latency:</strong> Full-duplex bidirectional voice-to-voice stream.<br />
<strong>Auto Failover:</strong> Drops gracefully to Local STT + Ollama + TTS if network drops.<br />
<strong>Stream Uptime:</strong> {realtimeVoice.streamUptime}% across all regional connections.
</Typography>
</Box>
</DoubleBezelCard>
{/* SQLite Vector RAG Knowledge Base */}
<DoubleBezelCard interactive bezelPadding="6px" innerPadding="24px">
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<StatRing color="green" size={48}>
<svg width="22" height="22" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
</svg>
</StatRing>
<Box>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '16px', fontWeight: 700, color: C.bright }}>
SQLite Vector RAG Engine
</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '11px', color: C.green400 }}>
{ragVector.embeddingModel}
</Typography>
</Box>
</Box>
<Box component="span" sx={statusBadgeSx('green')}>
KNOWLEDGE BASE
</Box>
</Box>
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 1.5, mb: 2.5 }}>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>INDEXED DOCS</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.bright }}>
{ragVector.indexedDocuments.toLocaleString()}
</Typography>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>VECTOR CHUNKS</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.cyanLight }}>
{ragVector.totalVectorChunks.toLocaleString()}
</Typography>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>SEARCH HIT RATE</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '16px', fontWeight: 700, color: C.green400 }}>
{ragVector.topHitRatePercent}%
</Typography>
</Box>
</Box>
<Box sx={{ p: 1.5, borderRadius: '10px', bgcolor: 'rgba(10, 17, 31, 0.5)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '12px', color: C.text, lineHeight: 1.6 }}>
<strong>Local Vector Store:</strong> Zero-cloud-leakage SQLite embeddings with cosine similarity.<br />
<strong>Average Search Latency:</strong> {ragVector.avgSearchLatencyMs}ms per 512-dim query.<br />
<strong>Semantic Q&A:</strong> Grounded context injection into Voice Mode & Meeting Summary.
</Typography>
</Box>
</DoubleBezelCard>
</Box>
{/* Bottom Full-Width: Meeting Intelligence & Speaker Diarization (Phase 14~15.5) */}
<DoubleBezelCard interactive bezelPadding="6px" innerPadding="24px">
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2.5 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<StatRing color="accent" size={52}>
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
</StatRing>
<Box>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '18px', fontWeight: 700, color: C.bright }}>
Meeting Intelligence & Speaker Diarization (Phase 14~15.5)
</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '12px', color: C.accentLight }}>
{meetingIntelligence.diarizationEngine}
</Typography>
</Box>
</Box>
<Box component="span" sx={statusBadgeSx('green')}>
PHASE 15.5 COMPLIANT
</Box>
</Box>
<Box sx={{ display: 'grid', gridTemplateColumns: { xs: '1fr', sm: 'repeat(2, 1fr)', md: 'repeat(4, 1fr)' }, gap: 2, mb: 3 }}>
<Box sx={{ p: 2, borderRadius: '12px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>SPEAKER ACCURACY</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '20px', fontWeight: 700, color: C.green400 }}>
{meetingIntelligence.speakerAccuracyPercent}%
</Typography>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '11px', color: C.dim, mt: 0.5 }}>
Pyannote + LLM Consensus
</Typography>
</Box>
<Box sx={{ p: 2, borderRadius: '12px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>ACTIVE MEETINGS</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '20px', fontWeight: 700, color: C.cyanLight }}>
{meetingIntelligence.activeMeetingSessions} Live
</Typography>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '11px', color: C.dim, mt: 0.5 }}>
Realtime Captions & Record
</Typography>
</Box>
<Box sx={{ p: 2, borderRadius: '12px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>TEMPLATES TODAY</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '20px', fontWeight: 700, color: C.purple400 }}>
{meetingIntelligence.templatesGeneratedToday} Docs
</Typography>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '11px', color: C.dim, mt: 0.5 }}>
Summary, Action Items, Jira
</Typography>
</Box>
<Box sx={{ p: 2, borderRadius: '12px', bgcolor: 'rgba(10, 17, 31, 0.7)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '10px', color: C.dim }}>MINDMAP EXPORTS</Typography>
<Typography sx={{ fontFamily: FONT_MONO, fontSize: '20px', fontWeight: 700, color: C.orange400 }}>
{meetingIntelligence.mindmapsExported} Maps
</Typography>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '11px', color: C.dim, mt: 0.5 }}>
Interactive Visual Graphs
</Typography>
</Box>
</Box>
<Box sx={{ p: 2, borderRadius: '12px', bgcolor: 'rgba(10, 17, 31, 0.5)', border: `1px solid ${C.border}` }}>
<Typography sx={{ fontFamily: FONT_SANS, fontSize: '13px', color: C.text, lineHeight: 1.7 }}>
<strong>Speaker Attribution Architecture:</strong> Hybrid pipeline combining Pyannote 3.1 voiceprint embeddings with LLM conversational speaker inference.<br />
<strong>Multi-Document Synthesis (Phase 14.5):</strong> Simultaneous generation of Executive Summary, Action Item Checklist, Jira Issue Drafts, and Interactive Markdown Mindmaps.<br />
<strong>File Transcription Pipeline:</strong> High-speed sequential STT for uploaded MP3/WAV audio recordings up to 4 hours.
</Typography>
</Box>
</DoubleBezelCard>
</Box>
</>
)
}