✓ Firecrawl API key configured
@@ -113,15 +180,20 @@ def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
with col2:
st.markdown("### AI Deep Research")
+ # Get existing API keys
+ existing_tavily_key = get_existing_api_key("TAVILY_API_KEY")
+ existing_metaphor_key = get_existing_api_key("METAPHOR_API_KEY")
+
tavily_key = st.text_input(
"Enter 🤖 Tavily API Key",
+ value=existing_tavily_key,
type="password",
key="tavily_key",
help="Enter your Tavily API key",
placeholder="AI-powered search with semantic understanding"
)
- if tavily_key:
+ if tavily_key or existing_tavily_key:
st.markdown("""
✓ Tavily API key configured
@@ -151,13 +223,14 @@ def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
metaphor_key = st.text_input(
"Enter 🧠 Metaphor/Exa API Key",
+ value=existing_metaphor_key,
type="password",
key="metaphor_key",
help="Enter your Metaphor/Exa API key",
placeholder="Neural search engine for deep research"
)
- if metaphor_key:
+ if metaphor_key or existing_metaphor_key:
st.markdown("""
✓ API key configured
@@ -194,23 +267,23 @@ def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
if render_navigation_buttons(3, 5, changes_made):
if changes_made:
try:
- # Load existing .env file if it exists
- load_dotenv()
+ # Prepare API keys dictionary with only non-empty values
+ api_keys = {}
+ if serpapi_key:
+ api_keys['SERPAPI_KEY'] = serpapi_key
+ if tavily_key:
+ api_keys['TAVILY_API_KEY'] = tavily_key
+ if metaphor_key:
+ api_keys['METAPHOR_API_KEY'] = metaphor_key
+ if firecrawl_key:
+ api_keys['FIRECRAWL_API_KEY'] = firecrawl_key
- # Create or update .env file with new API keys
- with open('.env', 'a') as f:
- if serpapi_key:
- f.write(f"\nSERPAPI_KEY={serpapi_key}")
- logger.info("[render_ai_research_setup] Saved SerpAPI key")
- if tavily_key:
- f.write(f"\nTAVILY_API_KEY={tavily_key}")
- logger.info("[render_ai_research_setup] Saved Tavily API key")
- if metaphor_key:
- f.write(f"\nMETAPHOR_API_KEY={metaphor_key}")
- logger.info("[render_ai_research_setup] Saved Metaphor API key")
- if firecrawl_key:
- f.write(f"\nFIRECRAWL_API_KEY={firecrawl_key}")
- logger.info("[render_ai_research_setup] Saved Firecrawl API key")
+ # Update .env file with new API keys
+ update_env_file(api_keys)
+
+ # Update environment variables
+ for key, value in api_keys.items():
+ os.environ[key] = value
# Store the API keys in session state
st.session_state['api_keys'] = {
diff --git a/lib/utils/api_key_manager/components/alwrity_integrations.py b/lib/utils/api_key_manager/components/alwrity_integrations.py
index 9f11b2e1..adf00eaf 100644
--- a/lib/utils/api_key_manager/components/alwrity_integrations.py
+++ b/lib/utils/api_key_manager/components/alwrity_integrations.py
@@ -7,6 +7,42 @@ from typing import Dict, Any
from ..manager import APIKeyManager
from .base import render_navigation_buttons, render_step_indicator, render_tab_style
+def update_env_file(env_vars: Dict[str, str]) -> None:
+ """Update the .env file with new environment variables, avoiding duplicates.
+
+ Args:
+ env_vars (Dict[str, str]): Dictionary of environment variables to update
+ """
+ try:
+ # Read existing .env file content
+ env_content = []
+ if os.path.exists('.env'):
+ with open('.env', 'r') as f:
+ env_content = f.readlines()
+
+ # Remove trailing newlines and empty lines
+ env_content = [line.strip() for line in env_content if line.strip()]
+
+ # Create a dictionary of existing variables
+ env_dict = {}
+ for line in env_content:
+ if '=' in line:
+ key, value = line.split('=', 1)
+ env_dict[key.strip()] = value.strip()
+
+ # Update with new values
+ env_dict.update(env_vars)
+
+ # Write back to .env file
+ with open('.env', 'w') as f:
+ for key, value in env_dict.items():
+ f.write(f"{key}={value}\n")
+
+ logger.info("[update_env_file] Successfully updated .env file")
+ except Exception as e:
+ logger.error(f"[update_env_file] Error updating .env file: {str(e)}")
+ raise
+
def render_alwrity_integrations(api_key_manager: APIKeyManager) -> Dict[str, Any]:
"""Render the ALwrity integrations setup step."""
try:
@@ -151,29 +187,33 @@ def render_alwrity_integrations(api_key_manager: APIKeyManager) -> Dict[str, Any
# Navigation buttons
if render_navigation_buttons(5, 6, changes_made):
if has_valid_integrations:
- # Store integration settings in session state
- st.session_state['integrations'] = {
- 'coming_soon': {
- 'wordpress': True,
- 'wix': True,
- 'facebook': True,
- 'instagram': True,
- 'google_search_console': True
- }
- }
-
- # Set INTEGRATION_DONE to True in .env file and environment
try:
- with open('.env', 'a') as f:
- f.write("\nINTEGRATION_DONE=True")
- os.environ['INTEGRATION_DONE'] = "True"
- logger.info("Set INTEGRATION_DONE=True in .env and environment")
+ # Store integration settings in session state
+ st.session_state['integrations'] = {
+ 'coming_soon': {
+ 'wordpress': True,
+ 'wix': True,
+ 'facebook': True,
+ 'instagram': True,
+ 'google_search_console': True
+ }
+ }
+
+ # Update INTEGRATION_DONE in .env file and environment
+ env_vars = {'INTEGRATION_DONE': 'True'}
+ update_env_file(env_vars)
+
+ # Update environment variable
+ os.environ['INTEGRATION_DONE'] = 'True'
+ logger.info("Updated INTEGRATION_DONE status")
+
+ # Update progress and move to next step
+ st.session_state['current_step'] = 6
+ st.rerun()
except Exception as e:
- logger.error(f"Failed to set INTEGRATION_DONE: {str(e)}")
-
- # Update progress and move to next step
- st.session_state['current_step'] = 6
- st.rerun()
+ error_msg = f"Failed to update integration status: {str(e)}"
+ logger.error(error_msg)
+ st.error(error_msg)
else:
st.error("Please configure at least one integration to continue")
diff --git a/lib/utils/api_key_manager/components/website_setup.py b/lib/utils/api_key_manager/components/website_setup.py
index ff260ee7..278da58c 100644
--- a/lib/utils/api_key_manager/components/website_setup.py
+++ b/lib/utils/api_key_manager/components/website_setup.py
@@ -15,7 +15,7 @@ import os
logger.remove() # Remove default handler
logger.add(
"logs/website_setup.log",
- rotation="500 MB",
+ rotation="50 MB",
retention="10 days",
level="DEBUG",
format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}"
@@ -26,6 +26,9 @@ logger.add(
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {message}"
)
+# Ensure logs directory exists
+os.makedirs("logs", exist_ok=True)
+
def render_website_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
"""Render the website setup step.
@@ -43,24 +46,67 @@ def render_website_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]:
col1, col2 = st.columns([1, 1])
with col1:
- url = st.text_input("Enter your website URL, if you own one", placeholder="https://example.com")
+ # Get existing website URL from environment or .env file
+ existing_url = os.getenv('WEBSITE_URL', None)
+ if not existing_url and os.path.exists('.env'):
+ try:
+ with open('.env', 'r') as f:
+ for line in f:
+ if line.strip().startswith('WEBSITE_URL='):
+ existing_url = line.strip().split('=')[1]
+ break
+ except Exception as e:
+ logger.error(f"[render_website_setup] Failed to read existing URL from .env: {str(e)}")
+
+ # If existing_url is 'no_website_provided', set it to empty for better UX
+ if existing_url == 'no_website_provided':
+ existing_url = ''
+
+ url = st.text_input(
+ "Enter your website URL, if you own one",
+ value=existing_url if existing_url else "",
+ placeholder="https://example.com"
+ )
logger.info(f"[render_website_setup] URL input value: {url}")
# Save URL to .env file
try:
+ # Check if WEBSITE_URL already exists in .env file
+ website_url_exists = False
+ env_lines = []
+
+ if os.path.exists('.env'):
+ with open('.env', 'r') as f:
+ for line in f:
+ if line.strip().startswith('WEBSITE_URL='):
+ website_url_exists = True
+ # Replace the existing WEBSITE_URL line with the new value
+ if url:
+ env_lines.append(f"WEBSITE_URL={url}\n")
+ else:
+ env_lines.append("WEBSITE_URL=no_website_provided\n")
+ else:
+ env_lines.append(line)
+
+ # If WEBSITE_URL doesn't exist, add it
+ if not website_url_exists:
+ if url:
+ env_lines.append(f"WEBSITE_URL={url}\n")
+ else:
+ env_lines.append("WEBSITE_URL=no_website_provided\n")
+
+ # Write all lines back to the .env file
+ with open('.env', 'w') as f:
+ f.writelines(env_lines)
+
+ # Set environment variable
if url:
- # Save to .env file
- with open('.env', 'a') as f:
- f.write(f"\nWEBSITE_URL={url}")
- # Set environment variable
os.environ['WEBSITE_URL'] = url
logger.info(f"[render_website_setup] Saved website URL to .env: {url}")
else:
- # Set default value if no URL provided
- with open('.env', 'a') as f:
- f.write("\nWEBSITE_URL=no_website_provided")
os.environ['WEBSITE_URL'] = "no_website_provided"
logger.info("[render_website_setup] Set default website URL: no_website_provided")
+
except Exception as e:
logger.error(f"[render_website_setup] Failed to save website URL: {str(e)}")
diff --git a/lib/workspace/alwrity_config/main_config.json b/lib/workspace/alwrity_config/main_config.json
index cbe9e4b9..dbed441a 100644
--- a/lib/workspace/alwrity_config/main_config.json
+++ b/lib/workspace/alwrity_config/main_config.json
@@ -1,7 +1,7 @@
{
"Blog Content Characteristics": {
"Blog Length": "2000",
- "Blog Tone": "Casual",
+ "Blog Tone": "Professional",
"Blog Demographic": "Professional",
"Blog Type": "Informational",
"Blog Language": "English",
@@ -9,16 +9,14 @@
},
"Blog Images Details": {
"Image Generation Model": "stable-diffusion",
- "Number of Blog Images": 1
+ "Number of Blog Images": 1,
+ "Image Style": "Realistic"
},
"LLM Options": {
"GPT Provider": "google",
"Model": "gemini-1.5-flash-latest",
"Temperature": 0.7,
- "Top-p": 0.9,
- "Max Tokens": 4000,
- "Frequency Penalty": 1.0,
- "Presence Penalty": 1.0
+ "Max Tokens": 4000
},
"Search Engine Parameters": {
"Geographic Location": "us",