Update app.py
Browse files
app.py
CHANGED
@@ -95,32 +95,12 @@ append_answer_lock = threading.Lock()
|
|
95 |
# Initialize browser
|
96 |
browser = SimpleTextBrowser(request_kwargs={})
|
97 |
|
98 |
-
# Initialize tools
|
99 |
-
ti_tool = TextInspectorTool(None, 20000) # Will be updated with session-specific model
|
100 |
-
|
101 |
# Initialize vulnerability tools
|
102 |
cvedb_tool = CVEDBTool()
|
103 |
epss_tool = EpsTool()
|
104 |
nvd_tool = NvdTool()
|
105 |
kevin_tool = KevinTool()
|
106 |
|
107 |
-
# Default tools (will be updated with session-specific models)
|
108 |
-
WEB_TOOLS = [
|
109 |
-
web_search, # duckduckgo
|
110 |
-
VisitTool(browser),
|
111 |
-
PageUpTool(browser),
|
112 |
-
PageDownTool(browser),
|
113 |
-
FinderTool(browser),
|
114 |
-
FindNextTool(browser),
|
115 |
-
ArchiveSearchTool(browser),
|
116 |
-
] + ([ti_tool] if ti_tool else []) + [
|
117 |
-
cvedb_tool, # CVEDB Tool
|
118 |
-
# report_generator, # Report generation tool - COMMENTED: Only works locally
|
119 |
-
epss_tool, # EPSS Tool
|
120 |
-
nvd_tool, # NVD Tool
|
121 |
-
kevin_tool, # KEVin Tool
|
122 |
-
]
|
123 |
-
|
124 |
def validate_hf_api_key(api_key: str) -> tuple[bool, str]:
|
125 |
"""Validate Hugging Face API key by making a test request."""
|
126 |
if not api_key or not api_key.strip():
|
@@ -168,10 +148,19 @@ def create_model_with_api_key(hf_token: str, model_id: str = None) -> InferenceC
|
|
168 |
|
169 |
def create_tools_with_model(model: InferenceClientModel):
|
170 |
"""Create tools with the provided model."""
|
|
|
|
|
|
|
|
|
171 |
# Update text inspector tool with the model
|
|
|
172 |
ti_tool = TextInspectorTool(model, 20000)
|
173 |
|
174 |
-
|
|
|
|
|
|
|
|
|
175 |
web_search, # duckduckgo
|
176 |
VisitTool(browser),
|
177 |
PageUpTool(browser),
|
@@ -179,13 +168,15 @@ def create_tools_with_model(model: InferenceClientModel):
|
|
179 |
FinderTool(browser),
|
180 |
FindNextTool(browser),
|
181 |
ArchiveSearchTool(browser),
|
182 |
-
|
183 |
cvedb_tool, # CVEDB Tool
|
184 |
# report_generator, # Report generation tool - COMMENTED: Only works locally
|
185 |
epss_tool, # EPSS Tool
|
186 |
nvd_tool, # NVD Tool
|
187 |
kevin_tool, # KEVin Tool
|
188 |
]
|
|
|
|
|
189 |
|
190 |
# Agent creation in a factory function
|
191 |
def create_agent(hf_token: str = None, model_id: str = None, max_steps: int = 10):
|
@@ -199,6 +190,11 @@ def create_agent(hf_token: str = None, model_id: str = None, max_steps: int = 10
|
|
199 |
model = create_model_with_api_key(hf_token, model_id)
|
200 |
tools = create_tools_with_model(model)
|
201 |
|
|
|
|
|
|
|
|
|
|
|
202 |
agent = CodeAgent(
|
203 |
model=model,
|
204 |
tools=[visualizer] + tools,
|
@@ -211,9 +207,6 @@ def create_agent(hf_token: str = None, model_id: str = None, max_steps: int = 10
|
|
211 |
logger.info("Agent created successfully")
|
212 |
return agent
|
213 |
|
214 |
-
# Document inspection tool will be created per session
|
215 |
-
document_inspection_tool = None
|
216 |
-
|
217 |
def get_user_session(request: gr.Request) -> str:
|
218 |
"""Get or create a unique session ID for the user."""
|
219 |
if not request:
|
@@ -486,7 +479,12 @@ User Query: """
|
|
486 |
# Combine system prompt with user message
|
487 |
full_prompt = system_prompt + prompt
|
488 |
|
489 |
-
|
|
|
|
|
|
|
|
|
|
|
490 |
yield messages
|
491 |
|
492 |
logger.info(f"Starting agent interaction for session {session_id[:8]}...")
|
@@ -614,13 +612,18 @@ User Query: """
|
|
614 |
), file_uploads_log + [file_path]
|
615 |
|
616 |
def log_user_message(self, text_input, file_uploads_log):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
617 |
return (
|
618 |
-
|
619 |
-
+ (
|
620 |
-
f"\nYou have been provided with these files, which might be helpful or not: {file_uploads_log}"
|
621 |
-
if len(file_uploads_log) > 0
|
622 |
-
else ""
|
623 |
-
),
|
624 |
gr.Textbox(
|
625 |
value="",
|
626 |
interactive=False,
|
@@ -821,18 +824,20 @@ This AI agent specializes in automated vulnerability research and analysis, buil
|
|
821 |
setup_api_btn = gr.Button("Setup API Key", variant="secondary")
|
822 |
|
823 |
# If an upload folder is provided, enable the upload feature
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
|
|
|
|
836 |
|
837 |
# Powered by smolagents
|
838 |
with gr.Row():
|
@@ -1000,6 +1005,22 @@ This AI agent specializes in automated vulnerability research and analysis, buil
|
|
1000 |
variant="primary",
|
1001 |
)
|
1002 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1003 |
# Examples Section for Mobile
|
1004 |
with gr.Accordion("💡 Example Prompts", open=False):
|
1005 |
gr.Markdown("**Click any example below to populate your request field:**")
|
@@ -1129,7 +1150,7 @@ This AI agent specializes in automated vulnerability research and analysis, buil
|
|
1129 |
|
1130 |
demo.launch(
|
1131 |
debug=True,
|
1132 |
-
server_name="
|
1133 |
server_port=7860,
|
1134 |
share=False,
|
1135 |
**kwargs
|
@@ -1137,6 +1158,6 @@ This AI agent specializes in automated vulnerability research and analysis, buil
|
|
1137 |
|
1138 |
# can this fix ctrl-c no response? no
|
1139 |
try:
|
1140 |
-
GradioUI().launch(
|
1141 |
except KeyboardInterrupt:
|
1142 |
...
|
|
|
95 |
# Initialize browser
|
96 |
browser = SimpleTextBrowser(request_kwargs={})
|
97 |
|
|
|
|
|
|
|
98 |
# Initialize vulnerability tools
|
99 |
cvedb_tool = CVEDBTool()
|
100 |
epss_tool = EpsTool()
|
101 |
nvd_tool = NvdTool()
|
102 |
kevin_tool = KevinTool()
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
def validate_hf_api_key(api_key: str) -> tuple[bool, str]:
|
105 |
"""Validate Hugging Face API key by making a test request."""
|
106 |
if not api_key or not api_key.strip():
|
|
|
148 |
|
149 |
def create_tools_with_model(model: InferenceClientModel):
|
150 |
"""Create tools with the provided model."""
|
151 |
+
# Verify the model was created correctly
|
152 |
+
if model is None:
|
153 |
+
raise ValueError("Model is None, cannot create TextInspectorTool")
|
154 |
+
|
155 |
# Update text inspector tool with the model
|
156 |
+
# 20000 = maximum characters to read from files (text_limit)
|
157 |
ti_tool = TextInspectorTool(model, 20000)
|
158 |
|
159 |
+
# Verify the tool was created correctly
|
160 |
+
if ti_tool is None:
|
161 |
+
raise ValueError("Failed to create TextInspectorTool")
|
162 |
+
|
163 |
+
tools = [
|
164 |
web_search, # duckduckgo
|
165 |
VisitTool(browser),
|
166 |
PageUpTool(browser),
|
|
|
168 |
FinderTool(browser),
|
169 |
FindNextTool(browser),
|
170 |
ArchiveSearchTool(browser),
|
171 |
+
ti_tool, # TextInspectorTool - always available
|
172 |
cvedb_tool, # CVEDB Tool
|
173 |
# report_generator, # Report generation tool - COMMENTED: Only works locally
|
174 |
epss_tool, # EPSS Tool
|
175 |
nvd_tool, # NVD Tool
|
176 |
kevin_tool, # KEVin Tool
|
177 |
]
|
178 |
+
|
179 |
+
return tools
|
180 |
|
181 |
# Agent creation in a factory function
|
182 |
def create_agent(hf_token: str = None, model_id: str = None, max_steps: int = 10):
|
|
|
190 |
model = create_model_with_api_key(hf_token, model_id)
|
191 |
tools = create_tools_with_model(model)
|
192 |
|
193 |
+
# Verify that TextInspectorTool is in the tools list
|
194 |
+
has_text_inspector = any(hasattr(tool, 'name') and tool.name == 'inspect_file_as_text' for tool in tools)
|
195 |
+
if not has_text_inspector:
|
196 |
+
raise ValueError("TextInspectorTool not found in tools list")
|
197 |
+
|
198 |
agent = CodeAgent(
|
199 |
model=model,
|
200 |
tools=[visualizer] + tools,
|
|
|
207 |
logger.info("Agent created successfully")
|
208 |
return agent
|
209 |
|
|
|
|
|
|
|
210 |
def get_user_session(request: gr.Request) -> str:
|
211 |
"""Get or create a unique session ID for the user."""
|
212 |
if not request:
|
|
|
479 |
# Combine system prompt with user message
|
480 |
full_prompt = system_prompt + prompt
|
481 |
|
482 |
+
# Extract clean message for display (remove internal context)
|
483 |
+
display_message = prompt
|
484 |
+
if "[INTERNAL CONTEXT:" in prompt:
|
485 |
+
display_message = prompt.split("[INTERNAL CONTEXT:")[0].strip()
|
486 |
+
|
487 |
+
messages.append(gr.ChatMessage(role="user", content=display_message))
|
488 |
yield messages
|
489 |
|
490 |
logger.info(f"Starting agent interaction for session {session_id[:8]}...")
|
|
|
612 |
), file_uploads_log + [file_path]
|
613 |
|
614 |
def log_user_message(self, text_input, file_uploads_log):
|
615 |
+
# Create the user message for display (clean, without file info)
|
616 |
+
display_message = text_input
|
617 |
+
|
618 |
+
# Create the internal message for the agent (with file context)
|
619 |
+
internal_message = text_input
|
620 |
+
if len(file_uploads_log) > 0:
|
621 |
+
file_names = [os.path.basename(f) for f in file_uploads_log]
|
622 |
+
file_paths = [f for f in file_uploads_log] # Full paths
|
623 |
+
internal_message += f"\n\n[Uploaded files available: {', '.join(file_names)}. Use inspect_file_as_text(file_path='uploads/filename') to analyze them. Use the content as plain text context if readable, no need to parse or create complex functions.]"
|
624 |
+
|
625 |
return (
|
626 |
+
internal_message, # This goes to the agent (with file context)
|
|
|
|
|
|
|
|
|
|
|
627 |
gr.Textbox(
|
628 |
value="",
|
629 |
interactive=False,
|
|
|
824 |
setup_api_btn = gr.Button("Setup API Key", variant="secondary")
|
825 |
|
826 |
# If an upload folder is provided, enable the upload feature
|
827 |
+
# COMMENTED: File upload feature temporarily disabled - works but consumes too many steps for parsing
|
828 |
+
# TODO: Re-enable after optimizing TextInspectorTool to use fewer steps
|
829 |
+
# if self.file_upload_folder is not None:
|
830 |
+
# upload_file = gr.File(label="Upload a file")
|
831 |
+
# upload_status = gr.Textbox(
|
832 |
+
# label="Upload Status",
|
833 |
+
# interactive=False,
|
834 |
+
# visible=False,
|
835 |
+
# )
|
836 |
+
# upload_file.change(
|
837 |
+
# self.upload_file,
|
838 |
+
# [upload_file, file_uploads_log],
|
839 |
+
# [upload_status, file_uploads_log],
|
840 |
+
# )
|
841 |
|
842 |
# Powered by smolagents
|
843 |
with gr.Row():
|
|
|
1005 |
variant="primary",
|
1006 |
)
|
1007 |
|
1008 |
+
# File upload section for mobile (simple)
|
1009 |
+
# COMMENTED: File upload feature temporarily disabled - works but consumes too many steps for parsing
|
1010 |
+
# TODO: Re-enable after optimizing
|
1011 |
+
# if self.file_upload_folder is not None:
|
1012 |
+
# mobile_upload_file = gr.File(label="📎 Upload PDF/TXT file (optional)")
|
1013 |
+
# mobile_upload_status = gr.Textbox(
|
1014 |
+
# label="Upload Status",
|
1015 |
+
# interactive=False,
|
1016 |
+
# visible=False,
|
1017 |
+
# )
|
1018 |
+
# mobile_upload_file.change(
|
1019 |
+
# self.upload_file,
|
1020 |
+
# [mobile_upload_file, file_uploads_log],
|
1021 |
+
# [mobile_upload_status, file_uploads_log],
|
1022 |
+
# )
|
1023 |
+
|
1024 |
# Examples Section for Mobile
|
1025 |
with gr.Accordion("💡 Example Prompts", open=False):
|
1026 |
gr.Markdown("**Click any example below to populate your request field:**")
|
|
|
1150 |
|
1151 |
demo.launch(
|
1152 |
debug=True,
|
1153 |
+
server_name="localhost",
|
1154 |
server_port=7860,
|
1155 |
share=False,
|
1156 |
**kwargs
|
|
|
1158 |
|
1159 |
# can this fix ctrl-c no response? no
|
1160 |
try:
|
1161 |
+
GradioUI(file_upload_folder="uploads").launch()
|
1162 |
except KeyboardInterrupt:
|
1163 |
...
|