mishrabp commited on
Commit
9bd5a99
·
verified ·
1 Parent(s): 82162f9

Upload folder using huggingface_hub

Browse files
common/aagents/google_agent.py CHANGED
@@ -135,5 +135,6 @@ google_agent = Agent(
135
  - Respect timeouts and handle errors gracefully
136
  """,
137
  )
 
138
 
139
  __all__ = ["google_agent", "google_search", "google_search_recent", "duckduckgo_search", "fetch_page_content", "current_datetime"]
 
135
  - Respect timeouts and handle errors gracefully
136
  """,
137
  )
138
+ google_agent.description = "A Google search agent that finds accurate, up-to-date information and recent news using Google Search."
139
 
140
  __all__ = ["google_agent", "google_search", "google_search_recent", "duckduckgo_search", "fetch_page_content", "current_datetime"]
common/aagents/healthcare_agent.py CHANGED
@@ -6,7 +6,7 @@ from openai import AsyncOpenAI
6
 
7
  # Import tools
8
  from mcp.tools.rag_tool import rag_search, UserContext
9
- from mcp.tools.search_tools import duckduckgo_search
10
  from mcp.tools.time_tools import current_datetime
11
 
12
 
@@ -34,7 +34,7 @@ groq_model = OpenAIChatCompletionsModel(model="groq/compound", openai_client=gro
34
  healthcare_agent = Agent[UserContext](
35
  name="HealthcareRAGAgent",
36
  model=gemini_model,
37
- tools=[rag_search, duckduckgo_search],
38
  instructions="""
39
  You are a healthcare information retrieval agent. You retrieve information from tools and synthesize it into well-formatted markdown responses.
40
 
@@ -96,5 +96,6 @@ healthcare_agent = Agent[UserContext](
96
  - Accept useless RAG results without calling web search
97
  """,
98
  )
 
99
 
100
  __all__ = ["healthcare_agent"]
 
6
 
7
  # Import tools
8
  from mcp.tools.rag_tool import rag_search, UserContext
9
+ from mcp.tools.search_tools import duckduckgo_search, fetch_page_content
10
  from mcp.tools.time_tools import current_datetime
11
 
12
 
 
34
  healthcare_agent = Agent[UserContext](
35
  name="HealthcareRAGAgent",
36
  model=gemini_model,
37
+ tools=[rag_search, duckduckgo_search, fetch_page_content],
38
  instructions="""
39
  You are a healthcare information retrieval agent. You retrieve information from tools and synthesize it into well-formatted markdown responses.
40
 
 
96
  - Accept useless RAG results without calling web search
97
  """,
98
  )
99
+ healthcare_agent.description = "A healthcare agent that combines RAG (Retrieval Augmented Generation) with web search to answer medical questions."
100
 
101
  __all__ = ["healthcare_agent"]
common/aagents/news_agent.py CHANGED
@@ -3,7 +3,6 @@ import os
3
  from agents import Agent, OpenAIChatCompletionsModel
4
  from dotenv import load_dotenv
5
  from mcp.tools.news_tools import get_top_headlines, search_news, get_news_by_category
6
- from mcp.tools.search_tools import duckduckgo_search
7
  from mcp.tools.time_tools import current_datetime
8
  from openai import AsyncOpenAI
9
 
@@ -25,7 +24,7 @@ groq_model = OpenAIChatCompletionsModel(model="groq/compound", openai_client=gro
25
  news_agent = Agent(
26
  name="NewsAgent",
27
  model=gemini_model,
28
- tools=[current_datetime, get_top_headlines, search_news, get_news_by_category, duckduckgo_search],
29
  instructions="""
30
  You are a NewsAgent specialized in fetching and analyzing recent news articles and headlines.
31
  Your role is to provide users with up-to-date, relevant news information from reliable sources.
@@ -46,13 +45,8 @@ news_agent = Agent(
46
  - Categories: "business", "entertainment", "general", "health", "science", "sports", "technology"
47
  - Input: { "category": "business", "country": "us", "num_results": 5 }
48
 
49
- **FALLBACK TOOL (DuckDuckGo Search):**
50
- 4. 'duckduckgo_search': Use ONLY when NewsAPI tools fail or API key is missing
51
- - Set search_type to "news" for news-specific results
52
- - Input: { "query": "topic", "max_results": 5, "search_type": "news", "timelimit": "d" }
53
-
54
  **TIME CONTEXT:**
55
- 5. 'current_datetime': Use to provide current date/time context in your responses
56
  - Input: { "format": "natural" }
57
 
58
  ## Workflow
@@ -62,14 +56,11 @@ news_agent = Agent(
62
  - Topic-specific → use search_news
63
  - Category-specific → use get_news_by_category
64
 
65
- 2. **Try Primary Tools First**: Always attempt NewsAPI tools before fallback
66
-
67
- 3. **Fallback if Needed**: If NewsAPI returns an error (missing API key, no results),
68
- use duckduckgo_search with search_type="news"
69
 
70
- 4. **Include Time Context**: Use current_datetime to provide temporal context
71
 
72
- 5. **Format Response**: Present news in a clear, organized format with:
73
  - Headlines/titles
74
  - Sources
75
  - Publication dates
@@ -95,12 +86,12 @@ news_agent = Agent(
95
 
96
  - Always cite sources and include publication dates
97
  - Prioritize recent news (within last 7 days unless specified otherwise)
98
- - If API key is missing, inform the user and use the fallback tool
99
  - Never fabricate news or sources
100
  - Present news objectively without bias
101
  - Include URLs so users can read full articles
102
  - Use current_datetime to ensure temporal accuracy
103
  """,
104
  )
 
105
 
106
- __all__ = ["news_agent", "get_top_headlines", "search_news", "get_news_by_category", "duckduckgo_search", "current_datetime"]
 
3
  from agents import Agent, OpenAIChatCompletionsModel
4
  from dotenv import load_dotenv
5
  from mcp.tools.news_tools import get_top_headlines, search_news, get_news_by_category
 
6
  from mcp.tools.time_tools import current_datetime
7
  from openai import AsyncOpenAI
8
 
 
24
  news_agent = Agent(
25
  name="NewsAgent",
26
  model=gemini_model,
27
+ tools=[current_datetime, get_top_headlines, search_news, get_news_by_category],
28
  instructions="""
29
  You are a NewsAgent specialized in fetching and analyzing recent news articles and headlines.
30
  Your role is to provide users with up-to-date, relevant news information from reliable sources.
 
45
  - Categories: "business", "entertainment", "general", "health", "science", "sports", "technology"
46
  - Input: { "category": "business", "country": "us", "num_results": 5 }
47
 
 
 
 
 
 
48
  **TIME CONTEXT:**
49
+ 4. 'current_datetime': Use to provide current date/time context in your responses
50
  - Input: { "format": "natural" }
51
 
52
  ## Workflow
 
56
  - Topic-specific → use search_news
57
  - Category-specific → use get_news_by_category
58
 
59
+ 2. **Execute Search**: Use the appropriate NewsAPI tool.
 
 
 
60
 
61
+ 3. **Include Time Context**: Use current_datetime to provide temporal context.
62
 
63
+ 4. **Format Response**: Present news in a clear, organized format with:
64
  - Headlines/titles
65
  - Sources
66
  - Publication dates
 
86
 
87
  - Always cite sources and include publication dates
88
  - Prioritize recent news (within last 7 days unless specified otherwise)
 
89
  - Never fabricate news or sources
90
  - Present news objectively without bias
91
  - Include URLs so users can read full articles
92
  - Use current_datetime to ensure temporal accuracy
93
  """,
94
  )
95
+ news_agent.description = "A news agent that fetches top headlines and searches for news articles by category or topic."
96
 
97
+ __all__ = ["news_agent", "get_top_headlines", "search_news", "get_news_by_category", "current_datetime"]
common/aagents/search_agent.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Search agent module for comprehensive web searches."""
2
+ import os
3
+ from agents import Agent, OpenAIChatCompletionsModel
4
+ from openai import AsyncOpenAI
5
+ from dotenv import load_dotenv
6
+ from mcp.tools.search_tools import duckduckgo_search, fetch_page_content
7
+ from mcp.tools.time_tools import current_datetime
8
+
9
+ # ---------------------------------------------------------
10
+ # Load environment variables
11
+ # ---------------------------------------------------------
12
+ load_dotenv()
13
+
14
+ GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"
15
+ google_api_key = os.getenv('GOOGLE_API_KEY')
16
+ gemini_client = AsyncOpenAI(base_url=GEMINI_BASE_URL, api_key=google_api_key)
17
+ gemini_model = OpenAIChatCompletionsModel(model="gemini-2.0-flash-exp", openai_client=gemini_client)
18
+
19
+ search_agent = Agent(
20
+ name="Web Search Agent",
21
+ model=gemini_model,
22
+ tools=[current_datetime, duckduckgo_search, fetch_page_content],
23
+ instructions="""
24
+ You are a highly efficient and specialized **Web Search Agent** 🌐. Your sole function is to retrieve and analyze information from the internet using the **duckduckgo_search** and **fetch_page_content** functions. You must act as a digital librarian and researcher, providing synthesized, cited, and up-to-date answers.
25
+
26
+ ## Core Directives & Priorities
27
+ 1. **Time Awareness First:** ALWAYS invoke **current_datetime** at the very beginning of your execution to establish the current temporal context. This is crucial for answering questions about "today", "yesterday", or recent events.
28
+ 2. **Search Strategy:**
29
+ * Analyze the user's request and construct 1-3 targeted search queries.
30
+ * Use **duckduckgo_search** to find relevant information. Use the 'news' type for current events.
31
+ * **Mandatory Deep Dive:** You MUST select the **top 3** most relevant search results and use **fetch_page_content** to retrieve their full text. *Do not rely solely on the short search snippets.*
32
+ 3. **Synthesis & Answer Construction:**
33
+ * Read the fetched content thoroughly.
34
+ * Synthesize the information into a coherent answer.
35
+ * **Conflict Resolution:** If sources disagree, note the discrepancy and favor the most recent or authoritative source.
36
+ * **Citations:** You **must** cite your sources. At the end of your response, list the *Title* and *URL* of the pages you used.
37
+ 4. **Clarity:** Use professional, plain language. Use headings and bullet points for readability.
38
+ 5. **Data Gaps:** If you cannot find a conclusive answer after searching and fetching, state: **"A conclusive answer could not be verified by current web search results."**
39
+
40
+ ## Workflow Example
41
+ 1. Call `current_datetime()`.
42
+ 2. Call `duckduckgo_search(query="...")`.
43
+ 3. Loop through top 3 results: `fetch_page_content(url=...)`.
44
+ 4. Synthesize findings into final answer.
45
+
46
+ **Crucially, never fabricate information. Your answer must be grounded in the text you have fetched.**
47
+ """,
48
+ )
49
+ search_agent.description = "A web search agent that retrieves information using DuckDuckGo and fetches page content for detailed answers."
50
+
51
+ __all__ = ["search_agent"]
common/aagents/weather_agent.py CHANGED
@@ -32,7 +32,6 @@ groq_model = OpenAIChatCompletionsModel(model="groq/compound", openai_client=gro
32
  weather_agent = Agent(
33
  name="WeatherAgent",
34
  model=gemini_model, #"gpt-4o-mini",
35
- # description="An agent that can perform web searches using DuckDuckGo.",
36
  tools=[current_datetime, get_weather_forecast, search_weather_fallback_ddgs, search_weather_fallback_bs],
37
  instructions="""
38
  You are a Weather Forecast agent who forecasts weather information ONLY.
@@ -61,9 +60,7 @@ weather_agent = Agent(
61
  }.
62
  ]
63
  """,
64
- # output_type=AgentOutputSchema(list[searchResult], strict_json_schema=False),
65
- # output_type=list[dict], # safer than list[searchResult],
66
- # output_type=list[searchResult],
67
  )
 
68
 
69
  __all__ = ["weather_agent", "get_weather_forecast", "search_weather_fallback_ddgs", "search_weather_fallback_bs"]
 
32
  weather_agent = Agent(
33
  name="WeatherAgent",
34
  model=gemini_model, #"gpt-4o-mini",
 
35
  tools=[current_datetime, get_weather_forecast, search_weather_fallback_ddgs, search_weather_fallback_bs],
36
  instructions="""
37
  You are a Weather Forecast agent who forecasts weather information ONLY.
 
60
  }.
61
  ]
62
  """,
 
 
 
63
  )
64
+ weather_agent.description = "A weather agent that provides current and forecasted weather information for specific cities."
65
 
66
  __all__ = ["weather_agent", "get_weather_forecast", "search_weather_fallback_ddgs", "search_weather_fallback_bs"]
common/aagents/web_research_agent.py CHANGED
@@ -29,9 +29,7 @@ groq_client = AsyncOpenAI(base_url=GROQ_BASE_URL, api_key=groq_api_key)
29
  groq_model = OpenAIChatCompletionsModel(model="groq/compound", openai_client=groq_client)
30
 
31
  web_research_agent = Agent(
32
- name="WebResearchAgent",
33
  model="gpt-4o-mini",
34
- # description="An agent that can perform web searches using DuckDuckGo.",
35
  tools=[duckduckgo_search, fetch_page_content],
36
  instructions="""
37
  You are WebResearchAgent — an advanced internet research assistant with two core abilities:
@@ -79,5 +77,6 @@ IMPORTANT RULES
79
  """
80
  ,
81
  )
 
82
 
83
  __all__ = ["web_research_agent", "duckduckgo_search", "fetch_page_content", "searchQuery", "searchResult"]
 
29
  groq_model = OpenAIChatCompletionsModel(model="groq/compound", openai_client=groq_client)
30
 
31
  web_research_agent = Agent(
 
32
  model="gpt-4o-mini",
 
33
  tools=[duckduckgo_search, fetch_page_content],
34
  instructions="""
35
  You are WebResearchAgent — an advanced internet research assistant with two core abilities:
 
77
  """
78
  ,
79
  )
80
+ web_research_agent.description = "A deep research agent that performs extensive web searches and content fetching for complex research queries."
81
 
82
  __all__ = ["web_research_agent", "duckduckgo_search", "fetch_page_content", "searchQuery", "searchResult"]
common/aagents/yf_agent.py CHANGED
@@ -2,7 +2,7 @@
2
  import os
3
  from agents import Agent, OpenAIChatCompletionsModel
4
  from dotenv import load_dotenv
5
- from mcp.tools.yf_tools import get_summary, get_market_sentiment, get_history
6
  from mcp.tools.time_tools import current_datetime
7
  from openai import AsyncOpenAI
8
 
@@ -24,7 +24,7 @@ groq_model = OpenAIChatCompletionsModel(model="groq/compound", openai_client=gro
24
  yf_agent = Agent(
25
  name="YahooFinanceAgent",
26
  model=gemini_model,
27
- tools=[current_datetime, get_summary, get_market_sentiment, get_history],
28
  instructions="""
29
  You are a specialized **Financial Analysis Agent** 💰, expert in market research, financial data retrieval, and market analysis.
30
  Your primary role is to provide *actionable*, *data-driven*, and *concise* financial reports based on the available tools.
@@ -35,14 +35,16 @@ yf_agent = Agent(
35
  Financial data is extremely time-sensitive.
36
 
37
  2. **Financial Data Integrity:** Use the Yahoo Finance tools for specific stock/index data:
38
- - 'get_summary': Get latest summary information and intraday price data for a ticker
39
- - 'get_market_sentiment': Analyze recent price changes and provide market sentiment (Bullish/Bearish/Neutral)
40
- - 'get_history': Fetch historical price data for a given ticker
 
 
41
 
42
  Be precise about the date range and data source.
43
 
44
- 3. **Synthesis and Analysis:** Do not just list data. You must **synthesize** financial data (prices, volume, sentiment)
45
- to provide a complete analytical perspective (e.g., "Stock X is up 5% today driven by strong market momentum").
46
 
47
  4. **Professional Clarity:** Present information in a clear, professional, and structured format.
48
  Use numerical data and financial terminology correctly.
@@ -62,9 +64,12 @@ yf_agent = Agent(
62
 
63
  Tool: get_market_sentiment
64
  Input: { "symbol": "AAPL", "period": "1mo" }
65
-
66
- Tool: get_history
67
- Input: { "symbol": "AAPL", "period": "1mo" }
 
 
 
68
 
69
  ## Output Format Guidelines
70
 
@@ -74,5 +79,6 @@ yf_agent = Agent(
74
  * Always include a disclaimer: "This analysis is for informational purposes only and is not financial advice."
75
  """,
76
  )
 
77
 
78
- __all__ = ["yf_agent", "get_summary", "get_market_sentiment", "get_history", "current_datetime"]
 
2
  import os
3
  from agents import Agent, OpenAIChatCompletionsModel
4
  from dotenv import load_dotenv
5
+ from mcp.tools.yf_tools import get_summary, get_market_sentiment, get_history, get_analyst_recommendations, get_earnings_calendar
6
  from mcp.tools.time_tools import current_datetime
7
  from openai import AsyncOpenAI
8
 
 
24
  yf_agent = Agent(
25
  name="YahooFinanceAgent",
26
  model=gemini_model,
27
+ tools=[current_datetime, get_summary, get_market_sentiment, get_history, get_analyst_recommendations, get_earnings_calendar],
28
  instructions="""
29
  You are a specialized **Financial Analysis Agent** 💰, expert in market research, financial data retrieval, and market analysis.
30
  Your primary role is to provide *actionable*, *data-driven*, and *concise* financial reports based on the available tools.
 
35
  Financial data is extremely time-sensitive.
36
 
37
  2. **Financial Data Integrity:** Use the Yahoo Finance tools for specific stock/index data:
38
+ - 'get_summary': Get latest summary information and intraday price data for a ticker.
39
+ - 'get_market_sentiment': Analyze recent price changes and provide market sentiment (Bullish/Bearish/Neutral).
40
+ - 'get_history': Fetch historical price data for a given ticker.
41
+ - 'get_analyst_recommendations': Fetch latest analyst ratings (Buy/Sell/Hold) for a symbol to provide **trading recommendations**.
42
+ - 'get_earnings_calendar': Fetch upcoming earnings dates for a symbol.
43
 
44
  Be precise about the date range and data source.
45
 
46
+ 3. **Synthesis and Analysis:** Do not just list data. You must **synthesize** financial data (prices, volume, sentiment, recommendations)
47
+ to provide a complete analytical perspective (e.g., "Stock X is up 5% today driven by strong market momentum and a generic 'Buy' rating from analysts").
48
 
49
  4. **Professional Clarity:** Present information in a clear, professional, and structured format.
50
  Use numerical data and financial terminology correctly.
 
64
 
65
  Tool: get_market_sentiment
66
  Input: { "symbol": "AAPL", "period": "1mo" }
67
+
68
+ Tool: get_analyst_recommendations
69
+ Input: { "symbol": "AAPL" }
70
+
71
+ Tool: get_earnings_calendar
72
+ Input: { "symbol": "AAPL" }
73
 
74
  ## Output Format Guidelines
75
 
 
79
  * Always include a disclaimer: "This analysis is for informational purposes only and is not financial advice."
80
  """,
81
  )
82
+ yf_agent.description = "A financial analysis agent that provides stock summaries, market sentiment, and historical data using Yahoo Finance."
83
 
84
+ __all__ = ["yf_agent", "get_summary", "get_market_sentiment", "get_history", "get_analyst_recommendations", "get_earnings_calendar", "current_datetime"]
common/mcp/tools/time_tools.py CHANGED
@@ -18,6 +18,7 @@ def current_datetime(format: str = "natural") -> str:
18
  Returns:
19
  str: Current date and time in the specified format
20
  """
 
21
  now = datetime.now()
22
 
23
  # Natural format options
 
18
  Returns:
19
  str: Current date and time in the specified format
20
  """
21
+ print(f"[DEBUG] current_datetime called with format='{format}'")
22
  now = datetime.now()
23
 
24
  # Natural format options
common/mcp/tools/yf_tools.py CHANGED
@@ -37,6 +37,7 @@ def get_summary(symbol: str, period: str = "1d", interval: str = "1h") -> str:
37
  - Volume
38
  - Period and interval used
39
  """
 
40
  try:
41
  ticker = yf.Ticker(symbol)
42
 
@@ -109,6 +110,7 @@ def get_market_sentiment(symbol: str, period: str = "1mo") -> str:
109
  str
110
  A human-readable sentiment string including percentage change.
111
  """
 
112
  try:
113
  ticker = yf.Ticker(symbol)
114
 
@@ -164,6 +166,7 @@ def get_history(symbol: str, period: str = "1mo") -> str:
164
  str
165
  A formatted string showing the last 5 rows of historical prices (Open, High, Low, Close, Volume).
166
  """
 
167
  try:
168
  ticker = yf.Ticker(symbol)
169
 
@@ -190,3 +193,65 @@ def get_history(symbol: str, period: str = "1mo") -> str:
190
 
191
  except Exception as e:
192
  return f"Error fetching historical data for '{symbol}': {e}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  - Volume
38
  - Period and interval used
39
  """
40
+ print(f"[DEBUG] get_summary called for symbol='{symbol}', period='{period}', interval='{interval}'")
41
  try:
42
  ticker = yf.Ticker(symbol)
43
 
 
110
  str
111
  A human-readable sentiment string including percentage change.
112
  """
113
+ print(f"[DEBUG] get_market_sentiment called for symbol='{symbol}', period='{period}'")
114
  try:
115
  ticker = yf.Ticker(symbol)
116
 
 
166
  str
167
  A formatted string showing the last 5 rows of historical prices (Open, High, Low, Close, Volume).
168
  """
169
+ print(f"[DEBUG] get_history called for symbol='{symbol}', period='{period}'")
170
  try:
171
  ticker = yf.Ticker(symbol)
172
 
 
193
 
194
  except Exception as e:
195
  return f"Error fetching historical data for '{symbol}': {e}"
196
+
197
+ @function_tool
198
+ def get_analyst_recommendations(symbol: str) -> str:
199
+ """
200
+ Fetch analyst recommendations for a given ticker.
201
+
202
+ Parameters:
203
+ -----------
204
+ symbol : str
205
+ The ticker symbol.
206
+
207
+ Returns:
208
+ --------
209
+ str
210
+ Formatted string string of analyst recommendations.
211
+ """
212
+ print(f"[DEBUG] get_analyst_recommendations called for symbol='{symbol}'")
213
+ try:
214
+ ticker = yf.Ticker(symbol)
215
+ recs = ticker.recommendations
216
+ if recs is None or recs.empty:
217
+ return f"No analyst recommendations found for {symbol}."
218
+
219
+ # Format the last few recommendations
220
+ latest = recs.tail(5)
221
+ return f"Analyst Recommendations for {symbol}:\n{latest.to_string()}"
222
+ except Exception as e:
223
+ return f"Error fetching recommendations for '{symbol}': {e}"
224
+
225
+ @function_tool
226
+ def get_earnings_calendar(symbol: str) -> str:
227
+ """
228
+ Fetch the next earnings date for a ticker.
229
+
230
+ Parameters:
231
+ -----------
232
+ symbol : str
233
+ The ticker symbol.
234
+
235
+ Returns:
236
+ --------
237
+ str
238
+ Next earnings date info.
239
+ """
240
+ print(f"[DEBUG] get_earnings_calendar called for symbol='{symbol}'")
241
+ try:
242
+ ticker = yf.Ticker(symbol)
243
+ calendar = ticker.calendar
244
+ if calendar is None:
245
+ return f"No earnings calendar found for {symbol}."
246
+
247
+ # Handle dict (new yfinance) or DataFrame (old yfinance)
248
+ if isinstance(calendar, dict):
249
+ if not calendar:
250
+ return f"No earnings calendar found for {symbol}."
251
+ elif hasattr(calendar, 'empty') and calendar.empty:
252
+ return f"No earnings calendar found for {symbol}."
253
+
254
+ return f"Earnings Calendar for {symbol}:\n{calendar}"
255
+ except Exception as e:
256
+ return f"Error fetching earnings calendar for '{symbol}': {e}"
257
+
src/deep-research/app.py CHANGED
@@ -28,70 +28,82 @@ st.set_page_config(page_title="Deep Research AI", layout="wide", page_icon="🧠
28
  st.markdown("""
29
  <style>
30
  /* Global Defaults */
31
- .stApp {
32
  background-color: #f8f9fa;
33
  font-family: 'Inter', sans-serif;
 
34
  }
35
 
36
- /* Remove default Streamlit top padding but add space for Fixed Header - Revert: Just remove top padding */
37
  .block-container {
38
- padding-top: 1rem !important; /* Small buffer */
 
 
39
  }
40
 
41
- /* Sticky Header */
42
- header[data-testid="stHeader"] { display: none; } /* Hide default streamlit header */
 
 
 
43
 
44
- .header-container {
45
- position: sticky;
46
- top: 0;
47
- z-index: 999;
48
-
 
 
 
 
 
 
 
 
 
 
 
49
  background: linear-gradient(135deg, #0f2027 0%, #203a43 50%, #2c5364 100%);
50
- color: #ffffff;
51
- padding: 3rem 2rem;
52
- display: flex;
53
- justify-content: space-between;
54
- align-items: center;
55
- box-shadow: 0 4px 20px rgba(0,0,0,0.15);
56
-
57
- margin-top: -4rem; /* Pull up aggressively to cover top gap */
58
- margin-left: -5rem;
59
- margin-right: -5rem;
60
-
61
- border-bottom: none;
62
- border-radius: 0 0 1rem 1rem;
63
  }
64
-
65
- .app-brand {
66
- font-family: 'Inter', sans-serif;
67
- font-size: 1.6rem;
68
  font-weight: 700;
69
- letter-spacing: -0.02em;
70
- color: #ffffff;
71
- display: flex;
72
- gap: 0.75rem;
73
- align-items: center;
74
  }
75
 
76
  /* Centered Search Area */
77
  .search-wrapper {
78
  max-width: 800px;
79
- margin: 4rem auto 2rem auto;
80
  text-align: center;
 
81
  }
82
 
83
  .search-headline {
84
- font-size: 2.5rem;
85
  font-weight: 800;
86
  color: #111;
87
  margin-bottom: 0.5rem;
88
- letter-spacing: -0.03em;
89
  }
90
 
91
  .search-subtext {
92
- font-size: 1.1rem;
93
  color: #666;
94
- margin-bottom: 2.5rem;
 
 
 
 
 
 
 
95
  }
96
 
97
  /* Input styling override */
@@ -101,11 +113,8 @@ st.markdown("""
101
  padding: 1rem !important;
102
  background: white !important;
103
  box-shadow: 0 4px 12px rgba(0,0,0,0.03) !important;
104
- font-size: 1.1rem !important;
105
- }
106
- .stTextArea textarea:focus {
107
- border-color: #667eea !important;
108
- box-shadow: 0 4px 15px rgba(102, 126, 234, 0.1) !important;
109
  }
110
 
111
  /* Custom Button */
@@ -115,8 +124,9 @@ st.markdown("""
115
  border-radius: 30px !important;
116
  padding: 0.5rem 2rem !important;
117
  border: none !important;
118
- box-shadow: 0 4px 10px rgba(0,0,0,0.2) !important;
119
  transition: transform 0.1s ease;
 
 
120
  }
121
  .stButton button:hover {
122
  transform: scale(1.02);
@@ -127,11 +137,11 @@ st.markdown("""
127
  max-width: 850px;
128
  margin: 2rem auto;
129
  background: white;
130
- padding: 4rem;
131
- min-height: 800px;
132
- box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 20px 40px rgba(0,0,0,0.05);
133
  color: #2c3e50;
134
- border: 1px solid #f0f0f0;
135
  }
136
  </style>
137
  """, unsafe_allow_html=True)
@@ -221,13 +231,9 @@ async def run_research(query: str):
221
 
222
  # Custom Header
223
  st.markdown("""
224
- <div class="header-container">
225
- <div class="app-brand">
226
- <span>🧠</span> Deep Research <i>(OpenAI Agentic)</i>
227
- </div>
228
- <div>
229
- <!-- Could add profile or other links here -->
230
- </div>
231
  </div>
232
  """, unsafe_allow_html=True)
233
 
 
28
  st.markdown("""
29
  <style>
30
  /* Global Defaults */
31
+ .stApp, [data-testid="stAppViewContainer"] {
32
  background-color: #f8f9fa;
33
  font-family: 'Inter', sans-serif;
34
+ overflow-x: hidden !important; /* Force hide horizontal scroll */
35
  }
36
 
 
37
  .block-container {
38
+ max-width: 1200px;
39
+ padding-top: 2rem !important;
40
+ padding-bottom: 2rem !important;
41
  }
42
 
43
+ /* Remove default header decoration */
44
+ header[data-testid="stHeader"] {
45
+ background-color: transparent !important;
46
+ z-index: 100 !important;
47
+ }
48
 
49
+ div[data-testid="stDecoration"] {
50
+ display: none;
51
+ }
52
+
53
+ /* Hero Section (Matching Chatbot Style) */
54
+ .hero-container {
55
+ position: relative;
56
+ width: 100vw;
57
+ left: 50%;
58
+ right: 50%;
59
+ margin-left: -50vw;
60
+ margin-right: -50vw;
61
+ margin-top: -6rem; /* Pull up to cover top padding */
62
+ padding: 4rem 1rem 2rem 1rem; /* Extra top padding for status bar area */
63
+ text-align: center;
64
+ margin-bottom: 2rem;
65
  background: linear-gradient(135deg, #0f2027 0%, #203a43 50%, #2c5364 100%);
66
+ color: white;
67
+ box-shadow: 0 4px 15px rgba(0,0,0,0.1);
 
 
 
 
 
 
 
 
 
 
 
68
  }
69
+
70
+ .hero-title {
71
+ font-size: 2rem;
72
+ margin-bottom: 0.5rem;
73
  font-weight: 700;
74
+ }
75
+ .hero-subtitle {
76
+ font-size: 1rem;
77
+ opacity: 0.95;
78
+ font-weight: 400;
79
  }
80
 
81
  /* Centered Search Area */
82
  .search-wrapper {
83
  max-width: 800px;
84
+ margin: 2rem auto;
85
  text-align: center;
86
+ padding: 0 1rem;
87
  }
88
 
89
  .search-headline {
90
+ font-size: 2rem;
91
  font-weight: 800;
92
  color: #111;
93
  margin-bottom: 0.5rem;
 
94
  }
95
 
96
  .search-subtext {
97
+ font-size: 1rem;
98
  color: #666;
99
+ margin-bottom: 2rem;
100
+ }
101
+
102
+ /* Mobile font sizes */
103
+ @media (max-width: 768px) {
104
+ .search-headline {
105
+ font-size: 1.75rem;
106
+ }
107
  }
108
 
109
  /* Input styling override */
 
113
  padding: 1rem !important;
114
  background: white !important;
115
  box-shadow: 0 4px 12px rgba(0,0,0,0.03) !important;
116
+ font-size: 1rem !important; /* Proper reading size */
117
+ color: #333 !important;
 
 
 
118
  }
119
 
120
  /* Custom Button */
 
124
  border-radius: 30px !important;
125
  padding: 0.5rem 2rem !important;
126
  border: none !important;
 
127
  transition: transform 0.1s ease;
128
+ min-height: 48px; /* Large touch target */
129
+ white-space: nowrap !important; /* Prevent label wrapping */
130
  }
131
  .stButton button:hover {
132
  transform: scale(1.02);
 
137
  max-width: 850px;
138
  margin: 2rem auto;
139
  background: white;
140
+ padding: 2rem;
141
+ min-height: 600px;
142
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
143
  color: #2c3e50;
144
+ border-radius: 8px;
145
  }
146
  </style>
147
  """, unsafe_allow_html=True)
 
231
 
232
  # Custom Header
233
  st.markdown("""
234
+ <div class="hero-container">
235
+ <div class="hero-title">🧠 Deep Research</div>
236
+ <div class="hero-subtitle">OpenAI Agentic Research Assistant</div>
 
 
 
 
237
  </div>
238
  """, unsafe_allow_html=True)
239