From f3ac7986ec9a03c4a4d015e263ca4fab3b746300 Mon Sep 17 00:00:00 2001 From: josedario87 Date: Sun, 15 Feb 2026 20:05:27 -0600 Subject: [PATCH] feat: Add transcript engine API and connect ConversationHistory to real data - Add transcript-engine service that parses Claude Code JSONL transcripts with session listing, message extraction, token/stats analysis, and caching - Add transcript REST routes (sessions list, latest, by session ID, section filtering) - Rewrite ConversationHistory to fetch from /api/transcript/* instead of mock data - Add session pills for switching between conversation sessions - Add stats bar footer with model, duration, tokens, and tool count - Add TranscriptSession/TranscriptMessage types, ChatInput, InputSettings, PromptBar updates, TranscriptCard, and useVoiceCapture composable --- frontend/src/components/agent/ChatInput.vue | 16 +- .../components/agent/ConversationHistory.vue | 345 ++++++-- .../src/components/agent/InputSettings.vue | 328 +++++++ frontend/src/components/agent/PromptBar.vue | 31 +- .../src/components/agent/TranscriptCard.vue | 129 ++- frontend/src/composables/useVoiceCapture.ts | 806 ++++++++++++++++++ frontend/src/types/agent.ts | 18 + server/routes/index.ts | 15 + server/routes/transcript.ts | 81 ++ server/services/transcript-engine.ts | 574 +++++++++++++ 10 files changed, 2246 insertions(+), 97 deletions(-) create mode 100644 frontend/src/components/agent/InputSettings.vue create mode 100644 frontend/src/composables/useVoiceCapture.ts create mode 100644 server/routes/transcript.ts create mode 100644 server/services/transcript-engine.ts diff --git a/frontend/src/components/agent/ChatInput.vue b/frontend/src/components/agent/ChatInput.vue index a29fd85..4731288 100644 --- a/frontend/src/components/agent/ChatInput.vue +++ b/frontend/src/components/agent/ChatInput.vue @@ -5,6 +5,7 @@ const props = defineProps<{ placeholder?: string recording?: boolean historyActive?: boolean + settingsActive?: boolean autofocus?: boolean }>() @@ -12,6 +13,7 @@ const emit = defineEmits<{ submit: [text: string] mic: [] 'toggle-history': [] + 'toggle-settings': [] }>() const inputText = ref('') @@ -82,6 +84,17 @@ defineExpose({ focus }) + @@ -148,7 +161,8 @@ defineExpose({ focus }) color: rgba(139, 92, 246, 0.9); } -.ci-history.active { +.ci-history.active, +.ci-settings.active { background: rgba(255, 255, 255, 0.12); color: rgba(255, 255, 255, 0.7); } diff --git a/frontend/src/components/agent/ConversationHistory.vue b/frontend/src/components/agent/ConversationHistory.vue index a9db001..6a1fced 100644 --- a/frontend/src/components/agent/ConversationHistory.vue +++ b/frontend/src/components/agent/ConversationHistory.vue @@ -1,85 +1,205 @@ @@ -115,8 +235,53 @@ const mockEntries: ConversationEntry[] = [ border-radius: 8px; } +/* Session Pills */ +.session-pills { + display: flex; + gap: 6px; + overflow-x: auto; + padding-bottom: 8px; + margin-bottom: 8px; + scrollbar-width: none; +} + +.session-pills::-webkit-scrollbar { + display: none; +} + +.session-pill { + flex-shrink: 0; + font-size: 10px; + font-weight: 600; + padding: 3px 8px; + border-radius: 10px; + border: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(255, 255, 255, 0.04); + color: rgba(255, 255, 255, 0.5); + cursor: pointer; + transition: all 0.15s ease; + white-space: nowrap; +} + +.session-pill:hover { + background: rgba(255, 255, 255, 0.08); + color: rgba(255, 255, 255, 0.7); +} + +.session-pill.active { + background: rgba(139, 92, 246, 0.15); + border-color: rgba(139, 92, 246, 0.3); + color: rgba(139, 92, 246, 0.9); +} + +.pill-count { + opacity: 0.6; + margin-left: 2px; +} + +/* Message List */ .history-list { - max-height: 300px; + max-height: 220px; overflow-y: auto; display: flex; flex-direction: column; @@ -168,8 +333,13 @@ const mockEntries: ConversationEntry[] = [ color: rgba(255, 255, 255, 0.25); } -.method-icon { - color: rgba(255, 255, 255, 0.25); +.tool-badge { + font-size: 9px; + font-weight: 600; + padding: 1px 5px; + border-radius: 4px; + color: rgba(245, 158, 11, 0.9); + background: rgba(245, 158, 11, 0.12); } .entry-content { @@ -178,8 +348,57 @@ const mockEntries: ConversationEntry[] = [ color: rgba(255, 255, 255, 0.7); } +/* Stats Bar */ +.stats-bar { + display: flex; + align-items: center; + gap: 6px; + margin-top: 8px; + padding-top: 8px; + border-top: 1px solid rgba(255, 255, 255, 0.06); + font-family: monospace; + font-size: 10px; + color: rgba(255, 255, 255, 0.35); +} + +.stats-sep { + opacity: 0.4; +} + +/* States */ +.history-loading { + padding: 16px 0; + text-align: center; + color: rgba(255, 255, 255, 0.3); + font-size: 12px; +} + +.loading-dots { + animation: pulse 1s ease-in-out infinite; +} + +.history-error { + padding: 12px 0; + text-align: center; + color: rgba(239, 68, 68, 0.7); + font-size: 11px; +} + +.history-empty { + padding: 16px 0; + text-align: center; + color: rgba(255, 255, 255, 0.25); + font-size: 11px; + font-style: italic; +} + @keyframes slide-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } } + +@keyframes pulse { + 0%, 100% { opacity: 0.3; } + 50% { opacity: 1; } +} diff --git a/frontend/src/components/agent/InputSettings.vue b/frontend/src/components/agent/InputSettings.vue new file mode 100644 index 0000000..ba4894d --- /dev/null +++ b/frontend/src/components/agent/InputSettings.vue @@ -0,0 +1,328 @@ + + + + + diff --git a/frontend/src/components/agent/PromptBar.vue b/frontend/src/components/agent/PromptBar.vue index 76bc555..ea1e15b 100644 --- a/frontend/src/components/agent/PromptBar.vue +++ b/frontend/src/components/agent/PromptBar.vue @@ -1,8 +1,11 @@ @@ -187,7 +211,8 @@ onBeforeUnmount(() => { - + + @@ -197,10 +222,12 @@ onBeforeUnmount(() => { :placeholder="`Mensaje a ${agent.uiConfig?.label || agent.name}...`" :recording="isRecording" :history-active="showHistory" + :settings-active="showSettings" :autofocus="visible" @submit="handleSubmit" @mic="handleMic" @toggle-history="toggleHistory" + @toggle-settings="toggleSettings" /> diff --git a/frontend/src/components/agent/TranscriptCard.vue b/frontend/src/components/agent/TranscriptCard.vue index fc31eb4..d14572a 100644 --- a/frontend/src/components/agent/TranscriptCard.vue +++ b/frontend/src/components/agent/TranscriptCard.vue @@ -1,52 +1,62 @@