Skip to content

Commit 95bd6d5

Browse files
author
Sarang S
committed
latest changes
1 parent 8e3e9ce commit 95bd6d5

13 files changed

Lines changed: 485 additions & 72 deletions

File tree

agents/.env.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ OPENSEARCH_OAUTH_TOKEN_URL=
99
OPENSEARCH_MCP_SERVER_PATH=
1010
AZURE_OPENAI_API_KEY=
1111
AZURE_OPENAI_ENDPOINT=
12-
AZURE_API_VERSION=
12+
AZURE_API_VERSION=
13+
WEBEX_OAUTH_CODE=

agents/analyze_agent/agent.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# Sub-agent
1212
calling_agent = LlmAgent(
1313
model=LiteLlm(
14-
model="azure/gpt-4.1",
14+
model="azure/gpt-5.2",
1515
api_key=os.environ["AZURE_OPENAI_API_KEY"],
1616
api_base=os.environ["AZURE_OPENAI_ENDPOINT"],
1717
api_version=os.environ["AZURE_API_VERSION"],
@@ -123,7 +123,7 @@
123123
# Sub-agent
124124
contact_center_agent = LlmAgent(
125125
model=LiteLlm(
126-
model="azure/gpt-4.1",
126+
model="azure/gpt-5.2",
127127
api_key=os.environ["AZURE_OPENAI_API_KEY"],
128128
api_base=os.environ["AZURE_OPENAI_ENDPOINT"],
129129
api_version=os.environ["AZURE_API_VERSION"],
@@ -237,7 +237,7 @@
237237
name="analyze_agent",
238238
output_key="analyze_results",
239239
model=LiteLlm(
240-
model="azure/gpt-4.1",
240+
model="azure/gpt-5.2",
241241
api_key=os.environ["AZURE_OPENAI_API_KEY"],
242242
api_base=os.environ["AZURE_OPENAI_ENDPOINT"],
243243
api_version=os.environ["AZURE_API_VERSION"],

agents/oauth_manager.py

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
"""
2+
OAuth Token Manager for Webex Authorization Flow
3+
Handles OAuth 2.0 token exchange and automatic token refresh
4+
"""
5+
6+
import os
7+
import time
8+
import threading
9+
import requests
10+
from typing import Dict, Optional
11+
import logging
12+
13+
logging.basicConfig(level=logging.INFO)
14+
logger = logging.getLogger(__name__)
15+
16+
17+
class OAuthTokenManager:
18+
"""Manages OAuth tokens with automatic refresh"""
19+
20+
# OAuth Configuration
21+
TOKEN_URL = "https://idbrokerbts.webex.com/idb/oauth2/v1/access_token"
22+
CLIENT_ID = "C01f064fa44b651f556122470b80ca0f2a5021293e9dbde4d9e1fd079d4ddc16a"
23+
CLIENT_SECRET = "e1c077c7d1f0505683ab177be14baee6511474f04b08628085de8b6ee36b0d2c"
24+
REDIRECT_URI = "http://localhost:3000"
25+
STATE = "set_state_here"
26+
27+
# Token refresh interval (12 hours in seconds)
28+
REFRESH_INTERVAL = 12 * 60 * 60
29+
30+
def __init__(self):
31+
self.access_token: Optional[str] = None
32+
self.refresh_token: Optional[str] = None
33+
self.refresh_thread: Optional[threading.Thread] = None
34+
self.stop_refresh = threading.Event()
35+
36+
def exchange_code_for_tokens(self, code: str) -> Dict[str, any]:
37+
"""Exchange authorization code for access and refresh tokens"""
38+
data = {
39+
"grant_type": "authorization_code",
40+
"client_id": self.CLIENT_ID,
41+
"client_secret": self.CLIENT_SECRET,
42+
"code": code,
43+
"state": self.STATE,
44+
"redirect_uri": self.REDIRECT_URI
45+
}
46+
47+
headers = {
48+
"Content-Type": "application/x-www-form-urlencoded"
49+
}
50+
51+
logger.info("Exchanging authorization code for tokens...")
52+
response = requests.post(self.TOKEN_URL, data=data, headers=headers)
53+
response.raise_for_status()
54+
55+
tokens = response.json()
56+
logger.info(f"Successfully obtained tokens. Access token expires in {tokens.get('expires_in')} seconds")
57+
58+
return tokens
59+
60+
def refresh_access_token(self) -> Dict[str, any]:
61+
"""Refresh the access token using refresh token"""
62+
if not self.refresh_token:
63+
raise ValueError("No refresh token available")
64+
65+
data = {
66+
"grant_type": "refresh_token",
67+
"refresh_token": self.refresh_token,
68+
"client_id": self.CLIENT_ID,
69+
"client_secret": self.CLIENT_SECRET
70+
}
71+
72+
headers = {
73+
"Content-Type": "application/x-www-form-urlencoded"
74+
}
75+
76+
logger.info("Refreshing access token...")
77+
response = requests.post(self.TOKEN_URL, data=data, headers=headers)
78+
response.raise_for_status()
79+
80+
tokens = response.json()
81+
logger.info("Successfully refreshed access token")
82+
83+
return tokens
84+
85+
def set_environment_token(self, access_token: str):
86+
"""Set the access token in environment variable"""
87+
os.environ["AZURE_OPENAI_API_KEY"] = access_token
88+
self.access_token = access_token
89+
logger.info("Set AZURE_OPENAI_API_KEY environment variable")
90+
91+
def update_tokens(self, tokens: Dict[str, any]):
92+
"""Update tokens from API response"""
93+
self.access_token = tokens.get("access_token")
94+
self.refresh_token = tokens.get("refresh_token")
95+
96+
# Set environment variable
97+
if self.access_token:
98+
self.set_environment_token(self.access_token)
99+
100+
def start_token_refresh_loop(self):
101+
"""Start background thread to refresh token every 12 hours"""
102+
if self.refresh_thread and self.refresh_thread.is_alive():
103+
logger.warning("Token refresh loop already running")
104+
return
105+
106+
self.stop_refresh.clear()
107+
self.refresh_thread = threading.Thread(target=self._token_refresh_worker, daemon=True)
108+
self.refresh_thread.start()
109+
logger.info(f"Started token refresh loop (every {self.REFRESH_INTERVAL / 3600} hours)")
110+
111+
def stop_token_refresh_loop(self):
112+
"""Stop the background token refresh loop"""
113+
if self.refresh_thread and self.refresh_thread.is_alive():
114+
logger.info("Stopping token refresh loop...")
115+
self.stop_refresh.set()
116+
self.refresh_thread.join(timeout=5)
117+
118+
def _token_refresh_worker(self):
119+
"""Background worker that refreshes tokens periodically"""
120+
while not self.stop_refresh.is_set():
121+
# Wait for refresh interval
122+
if self.stop_refresh.wait(self.REFRESH_INTERVAL):
123+
break
124+
125+
# Refresh token
126+
try:
127+
tokens = self.refresh_access_token()
128+
self.update_tokens(tokens)
129+
logger.info("Token refresh successful")
130+
except Exception as e:
131+
logger.error(f"Failed to refresh token: {e}")
132+
133+
def initialize(self, authorization_code: Optional[str] = None):
134+
"""Initialize tokens from authorization code (from env var or parameter)"""
135+
# Check if AZURE_OPENAI_API_KEY is already set
136+
existing_token = os.getenv("AZURE_OPENAI_API_KEY")
137+
if existing_token:
138+
logger.info("AZURE_OPENAI_API_KEY already set in environment, skipping OAuth initialization")
139+
self.access_token = existing_token
140+
return {"access_token": existing_token, "source": "environment"}
141+
142+
# Get code from parameter or environment variable
143+
code = authorization_code or os.getenv("WEBEX_OAUTH_CODE")
144+
145+
if not code:
146+
raise ValueError("Authorization code not provided. Set WEBEX_OAUTH_CODE environment variable or pass as parameter.")
147+
148+
logger.info("Initializing OAuth with authorization code...")
149+
150+
# Exchange code for tokens
151+
tokens = self.exchange_code_for_tokens(code)
152+
153+
# Update tokens
154+
self.update_tokens(tokens)
155+
156+
# Start refresh loop
157+
self.start_token_refresh_loop()
158+
159+
return tokens
160+
161+
162+
# Global instance
163+
_token_manager: Optional[OAuthTokenManager] = None
164+
165+
166+
def get_token_manager() -> OAuthTokenManager:
167+
"""Get or create the global token manager instance"""
168+
global _token_manager
169+
if _token_manager is None:
170+
_token_manager = OAuthTokenManager()
171+
return _token_manager
172+
173+
174+
if __name__ == "__main__":
175+
# Run OAuth token manager
176+
manager = get_token_manager()
177+
178+
print("=" * 60)
179+
print("OAuth Token Manager")
180+
print("=" * 60)
181+
182+
# Check for authorization code
183+
code = os.getenv("WEBEX_OAUTH_CODE")
184+
if not code:
185+
print("\n✗ Error: WEBEX_OAUTH_CODE environment variable not set")
186+
print("\nPlease set the authorization code:")
187+
print(" export WEBEX_OAUTH_CODE='your_code_here'")
188+
exit(1)
189+
190+
try:
191+
print("\nInitializing OAuth flow...")
192+
tokens = manager.initialize()
193+
194+
print("\n" + "=" * 60)
195+
print("✓ Successfully obtained tokens!")
196+
print("=" * 60)
197+
print(f"\nAccess Token: {tokens['access_token'][:50]}...")
198+
print(f"Refresh Token: {tokens['refresh_token'][:50]}...")
199+
print(f"Token Type: {tokens['token_type']}")
200+
print(f"Expires In: {tokens['expires_in']} seconds ({tokens['expires_in'] / 3600:.1f} hours)")
201+
print(f"Scope: {tokens['scope']}")
202+
print("\n✓ AZURE_OPENAI_API_KEY environment variable has been set")
203+
print("✓ Token refresh loop started (will refresh every 12 hours)")
204+
205+
# Keep the script running to maintain the refresh loop
206+
print("\nPress Ctrl+C to exit...")
207+
try:
208+
while True:
209+
time.sleep(1)
210+
except KeyboardInterrupt:
211+
print("\nStopping token refresh loop...")
212+
manager.stop_token_refresh_loop()
213+
print("Goodbye!")
214+
215+
except Exception as e:
216+
print(f"\n✗ Error: {e}")
217+
import traceback
218+
traceback.print_exc()
219+
exit(1)

agents/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
google-adk>=0.1.0
22
python-dotenv>=1.0.0
33
mcp>=1.0.0
4+
requests>=2.31.0

agents/root_agent/.adk/session.db

8.39 MB
Binary file not shown.

agents/root_agent/agent.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,19 @@
22
from pathlib import Path
33
from dotenv import load_dotenv
44
from google.adk.agents import SequentialAgent
5+
import logging
56

67
# Load environment variables from agents/.env
78
env_path = Path(__file__).parent.parent / '.env'
89
load_dotenv(dotenv_path=env_path)
910

11+
12+
from oauth_manager import get_token_manager
13+
14+
oauth_manager = get_token_manager()
15+
oauth_manager.initialize()
16+
logging.info("✓ OAuth token initialized and refresh loop started")
17+
1018
from analyze_agent.agent import analyze_agent
1119
from search_agent.agent import search_agent
1220
from visualAgent.agent import sequence_diagram_agent

agents/search_agent/agent.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
env_path = Path(__file__).parent.parent / '.env'
1515
load_dotenv(dotenv_path=env_path)
1616

17-
UV_PATH = "/opt/homebrew/bin/uv"
17+
UV_PATH = "/Users/sarangsa/.local/bin/uv"
1818

1919
# Region to Index Mappings
2020
REGION_INDEX_MAPPING = {
@@ -31,7 +31,7 @@
3131
# Agent 1: Search Mobius logs in wxm-app indexes
3232
wxm_search_agent = LlmAgent(
3333
model=LiteLlm(
34-
model="azure/gpt-4.1",
34+
model="azure/gpt-5.2",
3535
api_key=os.environ["AZURE_OPENAI_API_KEY"],
3636
api_base=os.environ["AZURE_OPENAI_ENDPOINT"],
3737
api_version=os.environ["AZURE_API_VERSION"],
@@ -177,7 +177,7 @@
177177
# Agent 2: Extract session ID from Mobius logs
178178
session_extractor_agent = LlmAgent(
179179
model=LiteLlm(
180-
model="azure/gpt-4.1",
180+
model="azure/gpt-5.2",
181181
api_key=os.environ["AZURE_OPENAI_API_KEY"],
182182
api_base=os.environ["AZURE_OPENAI_ENDPOINT"],
183183
api_version=os.environ["AZURE_API_VERSION"],
@@ -227,7 +227,7 @@
227227
# Agent 3: Search SSE/MSE logs in wxcalling indexes
228228
wxcalling_search_agent = LlmAgent(
229229
model=LiteLlm(
230-
model="azure/gpt-4.1",
230+
model="azure/gpt-5.2",
231231
api_key=os.environ["AZURE_OPENAI_API_KEY"],
232232
api_base=os.environ["AZURE_OPENAI_ENDPOINT"],
233233
api_version=os.environ["AZURE_API_VERSION"],
@@ -327,7 +327,7 @@
327327
# Agent 4: Extract SSE Call-ID from SSE/MSE logs
328328
sse_callid_extractor_agent = LlmAgent(
329329
model=LiteLlm(
330-
model="azure/gpt-4.1",
330+
model="azure/gpt-5.2",
331331
api_key=os.environ["AZURE_OPENAI_API_KEY"],
332332
api_base=os.environ["AZURE_OPENAI_ENDPOINT"],
333333
api_version=os.environ["AZURE_API_VERSION"],
@@ -380,7 +380,7 @@
380380
# Agent 5: Search WxCAS logs in wxcalling indexes
381381
wxcas_search_agent = LlmAgent(
382382
model=LiteLlm(
383-
model="azure/gpt-4.1",
383+
model="azure/gpt-5.2",
384384
api_key=os.environ["AZURE_OPENAI_API_KEY"],
385385
api_base=os.environ["AZURE_OPENAI_ENDPOINT"],
386386
api_version=os.environ["AZURE_API_VERSION"],

0 commit comments

Comments
 (0)