From 501dadd265e939b070128039ee20edcd146c8fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8C=D1=8F=20=D0=93=D0=BB=D0=B0=D0=B7=D1=83?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2?= Date: Thu, 15 Jan 2026 04:23:27 +0300 Subject: [PATCH] Add AI provider and model info support across components --- src/components/app/AppHeader.js | 120 +++++++++++++++++++++++++ src/components/app/CheatingDaddyApp.js | 20 ++++- src/components/views/AssistantView.js | 26 +++--- 3 files changed, 153 insertions(+), 13 deletions(-) diff --git a/src/components/app/AppHeader.js b/src/components/app/AppHeader.js index c58bf7d..6d84dc9 100644 --- a/src/components/app/AppHeader.js +++ b/src/components/app/AppHeader.js @@ -186,6 +186,82 @@ export class AppHeader extends LitElement { .status-tooltip .tooltip-content { color: #f14c4c; } + + .model-info { + display: flex; + gap: 6px; + align-items: center; + } + + .model-badge { + font-size: 10px; + color: var(--text-muted); + background: var(--key-background); + padding: 2px 6px; + border-radius: 3px; + font-family: 'SF Mono', Monaco, monospace; + max-width: 100px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .model-badge-wrapper { + position: relative; + display: inline-flex; + } + + .model-badge-wrapper .model-tooltip { + position: absolute; + top: 100%; + right: 0; + margin-top: 8px; + background: var(--tooltip-bg, #1a1a1a); + color: var(--tooltip-text, #ffffff); + padding: 10px 14px; + border-radius: 6px; + font-size: 12px; + white-space: nowrap; + opacity: 0; + visibility: hidden; + transition: opacity 0.15s ease, visibility 0.15s ease; + pointer-events: none; + box-shadow: 0 4px 12px rgba(0,0,0,0.3); + z-index: 1000; + } + + .model-badge-wrapper .model-tooltip::before { + content: ''; + position: absolute; + bottom: 100%; + right: 16px; + border: 6px solid transparent; + border-bottom-color: var(--tooltip-bg, #1a1a1a); + } + + .model-badge-wrapper:hover .model-tooltip { + opacity: 1; + visibility: visible; + } + + .model-tooltip-row { + display: flex; + justify-content: space-between; + gap: 16px; + margin-bottom: 4px; + } + + .model-tooltip-row:last-child { + margin-bottom: 0; + } + + .model-tooltip-label { + opacity: 0.7; + } + + .model-tooltip-value { + font-family: 'SF Mono', Monaco, monospace; + } `; static properties = { @@ -200,6 +276,8 @@ export class AppHeader extends LitElement { onHideToggleClick: { type: Function }, isClickThrough: { type: Boolean, reflect: true }, updateAvailable: { type: Boolean }, + aiProvider: { type: String }, + modelInfo: { type: Object }, }; constructor() { @@ -216,6 +294,8 @@ export class AppHeader extends LitElement { this.isClickThrough = false; this.updateAvailable = false; this._timerInterval = null; + this.aiProvider = 'gemini'; + this.modelInfo = { model: '', visionModel: '', whisperModel: '' }; } connectedCallback() { @@ -337,6 +417,45 @@ export class AppHeader extends LitElement { return navigationViews.includes(this.currentView); } + getProviderDisplayName() { + const names = { + 'gemini': 'Gemini', + 'openai-realtime': 'OpenAI Realtime', + 'openai-sdk': 'OpenAI SDK' + }; + return names[this.aiProvider] || this.aiProvider; + } + + renderModelInfo() { + // Only show model info for OpenAI SDK provider + if (this.aiProvider !== 'openai-sdk' || !this.modelInfo) { + return ''; + } + + const { model, visionModel, whisperModel } = this.modelInfo; + + // Show a compact badge with tooltip for model details + return html` +
+ ${model || 'gpt-4o'} +
+
+ Text + ${model || 'gpt-4o'} +
+
+ Vision + ${visionModel || 'gpt-4o'} +
+
+ Speech + ${whisperModel || 'whisper-1'} +
+
+
+ `; + } + render() { const elapsedTime = this.getElapsedTime(); const isError = this.statusText && (this.statusText.toLowerCase().includes('error') || this.statusText.toLowerCase().includes('failed')); @@ -348,6 +467,7 @@ export class AppHeader extends LitElement {
${this.currentView === 'assistant' ? html` + ${this.renderModelInfo()} ${elapsedTime}
${shortStatus} diff --git a/src/components/app/CheatingDaddyApp.js b/src/components/app/CheatingDaddyApp.js index b568c87..1fde960 100644 --- a/src/components/app/CheatingDaddyApp.js +++ b/src/components/app/CheatingDaddyApp.js @@ -110,6 +110,8 @@ export class CheatingDaddyApp extends LitElement { _awaitingNewResponse: { state: true }, shouldAnimateResponse: { type: Boolean }, _storageLoaded: { state: true }, + aiProvider: { type: String }, + modelInfo: { type: Object }, }; constructor() { @@ -133,6 +135,8 @@ export class CheatingDaddyApp extends LitElement { this._currentResponseIsComplete = true; this.shouldAnimateResponse = false; this._storageLoaded = false; + this.aiProvider = 'gemini'; + this.modelInfo = { model: '', visionModel: '', whisperModel: '' }; // Load from storage this._loadFromStorage(); @@ -140,9 +144,10 @@ export class CheatingDaddyApp extends LitElement { async _loadFromStorage() { try { - const [config, prefs] = await Promise.all([ + const [config, prefs, openaiSdkCreds] = await Promise.all([ cheatingDaddy.storage.getConfig(), - cheatingDaddy.storage.getPreferences() + cheatingDaddy.storage.getPreferences(), + cheatingDaddy.storage.getOpenAISDKCredentials() ]); // Check onboarding status @@ -160,6 +165,14 @@ export class CheatingDaddyApp extends LitElement { this.selectedScreenshotInterval = prefs.selectedScreenshotInterval || '5'; this.selectedImageQuality = prefs.selectedImageQuality || 'medium'; this.layoutMode = config.layout || 'normal'; + + // Load AI provider and model info + this.aiProvider = prefs.aiProvider || 'gemini'; + this.modelInfo = { + model: openaiSdkCreds.model || 'gpt-4o', + visionModel: openaiSdkCreds.visionModel || 'gpt-4o', + whisperModel: openaiSdkCreds.whisperModel || 'whisper-1' + }; this._storageLoaded = true; this.updateLayoutMode(); @@ -487,6 +500,7 @@ export class CheatingDaddyApp extends LitElement { .responses=${this.responses} .currentResponseIndex=${this.currentResponseIndex} .selectedProfile=${this.selectedProfile} + .aiProvider=${this.aiProvider} .onSendText=${message => this.handleSendText(message)} .shouldAnimateResponse=${this.shouldAnimateResponse} @response-index-changed=${this.handleResponseIndexChanged} @@ -521,6 +535,8 @@ export class CheatingDaddyApp extends LitElement { .currentView=${this.currentView} .statusText=${this.statusText} .startTime=${this.startTime} + .aiProvider=${this.aiProvider} + .modelInfo=${this.modelInfo} .onCustomizeClick=${() => this.handleCustomizeClick()} .onHelpClick=${() => this.handleHelpClick()} .onHistoryClick=${() => this.handleHistoryClick()} diff --git a/src/components/views/AssistantView.js b/src/components/views/AssistantView.js index 1628263..18209ed 100644 --- a/src/components/views/AssistantView.js +++ b/src/components/views/AssistantView.js @@ -358,6 +358,7 @@ export class AssistantView extends LitElement { shouldAnimateResponse: { type: Boolean }, flashCount: { type: Number }, flashLiteCount: { type: Number }, + aiProvider: { type: String }, }; constructor() { @@ -368,6 +369,7 @@ export class AssistantView extends LitElement { this.onSendText = () => {}; this.flashCount = 0; this.flashLiteCount = 0; + this.aiProvider = 'gemini'; } getProfileNames() { @@ -658,23 +660,25 @@ export class AssistantView extends LitElement { Select region
-
-
- Flash - ${this.flashCount}/20 + ${this.aiProvider === 'gemini' ? html` +
+
+ Flash + ${this.flashCount}/20 +
+
+ Flash Lite + ${this.flashLiteCount}/20 +
+
Resets every 24 hours
-
- Flash Lite - ${this.flashLiteCount}/20 -
-
Resets every 24 hours
-
+ ` : ''}