jens.luecke commited on
Commit
098726a
Β·
1 Parent(s): 9a92021

Refactor iframe preview creation and enhance API key handling. Simplified iframe HTML structure and improved error messaging. Added model retrieval for non-Hugging Face providers in API key management.

Browse files
Files changed (1) hide show
  1. app.py +89 -123
app.py CHANGED
@@ -141,126 +141,20 @@ def start_preview_app():
141
 
142
 
143
  def create_iframe_preview():
144
- """Create an iframe HTML element for the preview."""
145
  print("πŸ”„ Creating iframe preview...")
146
  # Start the preview app
147
  success, message = start_preview_app()
148
 
149
  if not success:
150
  print(f"❌ Failed to create preview iframe: {message}")
151
- return f"""
152
- <div style='padding: 20px; text-align: center; color: #d32f2f;'>
153
- <h3>❌ Failed to start preview</h3>
154
- <pre style='background: #f5f5f5; padding: 10px; \
155
- border-radius: 4px; text-align: left;'>{message}</pre>
156
- </div>
157
- """
158
-
159
- # Add timestamp to force iframe refresh
160
- timestamp = int(time.time() * 1000)
161
- print("βœ… Iframe preview created successfully")
162
-
163
- return f"""
164
- <div style='width: 100%; height: 70vh; border: 1px solid #ddd; border-radius: \
165
- 8px; overflow: hidden; position: relative; background: #f9f9f9;'>
166
- <iframe
167
- id="preview-iframe-{timestamp}"
168
- src="{PREVIEW_URL}"
169
- width="100%"
170
- height="100%"
171
- frameborder="0"
172
- style="border: none; background: white;"
173
- sandbox="allow-same-origin allow-scripts allow-forms allow-popups \
174
- allow-top-navigation allow-modals"
175
- loading="eager"
176
- onload="document.getElementById('loading-{timestamp}').style.display='none'"
177
- onerror="document.getElementById('iframe-{timestamp}').style.display='none';\
178
- document.getElementById('fallback-{timestamp}').style.display='block'"
179
- ></iframe>
180
-
181
- <!-- Loading indicator -->
182
- <div id="loading-{timestamp}" style="position: absolute; top: 0; left: 0; \
183
- width: 100%; height: 100%; background: rgba(255,255,255,0.9); \
184
- display: flex; align-items: center; justify-content: center; z-index: 10;">
185
- <div style="text-align: center;">
186
- <div style="border: 4px solid #f3f3f3; border-top: 4px solid #007bff; \
187
- border-radius: 50%; width: 40px; height: 40px; animation: spin 1s \
188
- linear infinite; margin: 0 auto 15px;"></div>
189
- <p style="color: #666; margin: 0;">Loading preview...</p>
190
- </div>
191
- </div>
192
-
193
- <!-- Fallback content -->
194
- <div id="fallback-{timestamp}" style="display: none; padding: 20px; \
195
- text-align: center; height: 100%; display: flex; flex-direction: column; \
196
- justify-content: center;">
197
- <div style='background: white; border-radius: 8px; padding: 30px; \
198
- margin: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);'>
199
- <h3 style='color: #28a745; margin-bottom: 20px;'>
200
- πŸš€ Preview App Running!
201
- </h3>
202
- <p style='color: #666; margin-bottom: 25px; font-size: 16px;'>
203
- Your Gradio app is running successfully.
204
- </p>
205
- <div style='margin: 20px 0;'>
206
- <a href="{PREVIEW_URL}" target="_blank"
207
- style='display: inline-block; padding: 12px 25px; background: \
208
- #007bff; color: white;
209
- text-decoration: none; border-radius: 6px; \
210
- font-weight: bold; font-size: 16px;
211
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);'>
212
- πŸ”— Open Preview in New Tab
213
- </a>
214
- </div>
215
- <div style='margin-top: 20px; padding: 15px; background: #f8f9fa; \
216
- border-radius: 4px; border-left: 4px solid #007bff;'>
217
- <p style='margin: 0; color: #495057; font-size: 14px;'>
218
- <strong>URL:</strong> <code style='background: #e9ecef; \
219
- padding: 2px 6px; border-radius: 3px;'>{PREVIEW_URL}</code>
220
- </p>
221
- </div>
222
- </div>
223
- </div>
224
-
225
- <!-- Open in new tab button -->
226
- <div style='position: absolute; top: 10px; right: 10px; z-index: 20;'>
227
- <a href="{PREVIEW_URL}" target="_blank"
228
- style='display: inline-block; padding: 8px 12px; background: \
229
- rgba(0,0,0,0.8); color: white;
230
- text-decoration: none; border-radius: 4px; font-size: 12px;'>
231
- β†— Open in new tab
232
- </a>
233
- </div>
234
- </div>
235
-
236
- <div style='padding: 10px; text-align: center; color: #666; font-size: 12px;'>
237
- Preview running on <a href="{PREVIEW_URL}" target="_blank">{PREVIEW_URL}</a>
238
- <span style='margin-left: 10px; color: #999;'>
239
- Last updated: {time.strftime('%H:%M:%S')}
240
- </span>
241
- </div>
242
-
243
- <style>
244
- @keyframes spin {{
245
- 0% {{ transform: rotate(0deg); }}
246
- 100% {{ transform: rotate(360deg); }}
247
- }}
248
- </style>
249
-
250
- <script>
251
- // Auto-fallback after 10 seconds if iframe doesn't load
252
- setTimeout(function() {{
253
- const loading = document.getElementById('loading-{timestamp}');
254
- const fallback = document.getElementById('fallback-{timestamp}');
255
- if (loading && loading.style.display !== 'none') {{
256
- loading.style.display = 'none';
257
- if (fallback) {{
258
- fallback.style.display = 'flex';
259
- }}
260
- }}
261
- }}, 10000);
262
- </script>
263
- """
264
 
265
 
266
  def is_preview_running():
@@ -283,8 +177,22 @@ def ensure_preview_running():
283
  start_preview_app()
284
 
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  def save_api_key(provider, api_key):
287
- """Save API key to environment variable."""
288
  if not api_key.strip():
289
  return f"⚠️ Please enter a valid API key for {provider}"
290
 
@@ -299,8 +207,20 @@ def save_api_key(provider, api_key):
299
 
300
  env_var_name = env_var_map.get(provider)
301
  if env_var_name:
 
302
  os.environ[env_var_name] = api_key.strip()
303
- return f"βœ… {provider} API key saved successfully"
 
 
 
 
 
 
 
 
 
 
 
304
  else:
305
  return f"❌ Unknown provider: {provider}"
306
 
@@ -331,9 +251,15 @@ def get_api_key_status(selected_llm_provider="Anthropic"):
331
  if llm_env_var and os.getenv(llm_env_var):
332
  key = os.getenv(llm_env_var)
333
  masked_key = f"{key[:8]}...{key[-4:]}" if len(key) > 12 else "***"
334
- status.append(f"βœ… {selected_llm_provider}: {masked_key}")
 
335
  else:
336
- status.append(f"❌ {selected_llm_provider}: Not set")
 
 
 
 
 
337
 
338
  return "\n".join(status)
339
 
@@ -506,8 +432,8 @@ class GradioUI:
506
  label="Current API Key Status",
507
  value=get_api_key_status(),
508
  interactive=False,
509
- lines=2,
510
- max_lines=2,
511
  )
512
 
513
  # with gr.Row():
@@ -557,22 +483,33 @@ class GradioUI:
557
 
558
  # Set up event handlers for API key saving
559
  def save_and_update_status(
560
- provider, api_key, selected_llm_provider="Anthropic"
561
  ):
562
  message = save_api_key(provider, api_key)
563
  status = get_api_key_status(selected_llm_provider)
 
 
 
 
 
 
 
 
 
564
  return message, status, "" # Clear the input field
565
 
566
  hf_save_btn.click(
567
  lambda key, llm_prov: save_and_update_status(
568
- "Hugging Face", key, llm_prov
569
  ),
570
  inputs=[hf_token, llm_provider],
571
  outputs=[api_message, api_status, hf_token],
572
  ).then(lambda: gr.Textbox(visible=True), outputs=[api_message])
573
 
574
  llm_save_btn.click(
575
- lambda provider, key: save_and_update_status(provider, key, provider),
 
 
576
  inputs=[llm_provider, llm_token],
577
  outputs=[api_message, api_status, llm_token],
578
  ).then(lambda: gr.Textbox(visible=True), outputs=[api_message])
@@ -689,6 +626,35 @@ class GradioUI:
689
 
690
  return demo
691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
692
 
693
  if __name__ == "__main__":
694
  from kiss_agent import KISSAgent
 
141
 
142
 
143
  def create_iframe_preview():
144
+ """Create a simple iframe for the preview."""
145
  print("πŸ”„ Creating iframe preview...")
146
  # Start the preview app
147
  success, message = start_preview_app()
148
 
149
  if not success:
150
  print(f"❌ Failed to create preview iframe: {message}")
151
+ return f'<div style="padding: 20px; color: red;">\
152
+ ❌ Failed to start preview: {message}\
153
+ </div>'
154
+
155
+ print("βœ… Simple iframe preview created")
156
+ return f'<iframe src="{PREVIEW_URL}" width="100%" height="600px" frameborder="0">\
157
+ </iframe>'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
159
 
160
  def is_preview_running():
 
177
  start_preview_app()
178
 
179
 
180
+ def get_default_model_for_provider(provider: str) -> str:
181
+ """Get the default model ID for a given provider."""
182
+ provider_model_map = {
183
+ "Anthropic": "anthropic/claude-sonnet-4-20250514",
184
+ "OpenAI": "openai/gpt-4o",
185
+ "Mistral": "mistral/codestral-latest",
186
+ "SambaNova": "sambanova/Meta-Llama-3.1-70B-Instruct",
187
+ "Hugging Face": "huggingface/together/Qwen/Qwen2.5-Coder-32B-Instruct",
188
+ }
189
+ return provider_model_map.get(
190
+ provider, "huggingface/together/Qwen/Qwen2.5-Coder-32B-Instruct"
191
+ )
192
+
193
+
194
  def save_api_key(provider, api_key):
195
+ """Save API key to environment variable and update model accordingly."""
196
  if not api_key.strip():
197
  return f"⚠️ Please enter a valid API key for {provider}"
198
 
 
207
 
208
  env_var_name = env_var_map.get(provider)
209
  if env_var_name:
210
+ # Always set the provider-specific API key
211
  os.environ[env_var_name] = api_key.strip()
212
+
213
+ # For non-Hugging Face providers, also set the generic API_KEY and MODEL_ID
214
+ # This ensures the main agent uses the correct model and API key
215
+ if provider != "Hugging Face":
216
+ os.environ["API_KEY"] = api_key.strip()
217
+ os.environ["MODEL_ID"] = get_default_model_for_provider(provider)
218
+ return (
219
+ f"βœ… {provider} API key saved successfully \n"
220
+ f"Model: {get_default_model_for_provider(provider)}"
221
+ )
222
+ else:
223
+ return f"βœ… {provider} API key saved successfully"
224
  else:
225
  return f"❌ Unknown provider: {provider}"
226
 
 
251
  if llm_env_var and os.getenv(llm_env_var):
252
  key = os.getenv(llm_env_var)
253
  masked_key = f"{key[:8]}...{key[-4:]}" if len(key) > 12 else "***"
254
+ model = get_default_model_for_provider(selected_llm_provider)
255
+ status.append(f"βœ… {selected_llm_provider}: {masked_key} (Model: {model})")
256
  else:
257
+ model = get_default_model_for_provider(selected_llm_provider)
258
+ status.append(f"❌ {selected_llm_provider}: Not set (Would use: {model})")
259
+
260
+ # Show current active model
261
+ current_model = os.getenv("MODEL_ID", "Qwen/Qwen2.5-Coder-32B-Instruct")
262
+ status.append(f"πŸ€– Current Active Model: {current_model}")
263
 
264
  return "\n".join(status)
265
 
 
432
  label="Current API Key Status",
433
  value=get_api_key_status(),
434
  interactive=False,
435
+ lines=4,
436
+ max_lines=4,
437
  )
438
 
439
  # with gr.Row():
 
483
 
484
  # Set up event handlers for API key saving
485
  def save_and_update_status(
486
+ provider, api_key, selected_llm_provider="Anthropic", session_state=None
487
  ):
488
  message = save_api_key(provider, api_key)
489
  status = get_api_key_status(selected_llm_provider)
490
+
491
+ # If this is an LLM provider (not Hugging Face), recreate the agent
492
+ if provider != "Hugging Face" and session_state is not None:
493
+ agent_message = self.recreate_agent_with_new_model(
494
+ session_state, provider
495
+ )
496
+ if agent_message:
497
+ message += f"\n{agent_message}"
498
+
499
  return message, status, "" # Clear the input field
500
 
501
  hf_save_btn.click(
502
  lambda key, llm_prov: save_and_update_status(
503
+ "Hugging Face", key, llm_prov, session_state
504
  ),
505
  inputs=[hf_token, llm_provider],
506
  outputs=[api_message, api_status, hf_token],
507
  ).then(lambda: gr.Textbox(visible=True), outputs=[api_message])
508
 
509
  llm_save_btn.click(
510
+ lambda provider, key: save_and_update_status(
511
+ provider, key, provider, session_state
512
+ ),
513
  inputs=[llm_provider, llm_token],
514
  outputs=[api_message, api_status, llm_token],
515
  ).then(lambda: gr.Textbox(visible=True), outputs=[api_message])
 
626
 
627
  return demo
628
 
629
+ def recreate_agent_with_new_model(self, session_state, provider=None):
630
+ """Recreate the agent with updated model configuration."""
631
+ from kiss_agent import KISSAgent
632
+
633
+ # Get the new model ID if provider is specified
634
+ if provider and provider != "Hugging Face":
635
+ model_id = get_default_model_for_provider(provider)
636
+
637
+ # Get API key from provider-specific environment variable
638
+ env_var_map = {
639
+ "Anthropic": "ANTHROPIC_API_KEY",
640
+ "OpenAI": "OPENAI_API_KEY",
641
+ "SambaNova": "SAMBANOVA_API_KEY",
642
+ "Mistral": "MISTRAL_API_KEY",
643
+ }
644
+
645
+ env_var_name = env_var_map.get(provider)
646
+ api_key = os.getenv(env_var_name) if env_var_name else None
647
+
648
+ if not api_key:
649
+ return f"❌ No API key found for {provider}"
650
+
651
+ # Create new agent with updated model
652
+ new_agent = KISSAgent(model_id=model_id, api_key=api_key)
653
+ session_state["agent"] = new_agent
654
+
655
+ return f"πŸ”„ Agent updated to use {provider} model: {model_id}"
656
+ return ""
657
+
658
 
659
  if __name__ == "__main__":
660
  from kiss_agent import KISSAgent