Skip to content

Commit 5b9fa2f

Browse files
committed
Implement Gemini code assist recommendations and fix pre-commit issues
Apply code quality improvements suggested by Gemini code assist: - Enhanced error pattern matching with more specific message detection - Smart dynamic fallback logic based on which model actually failed - Centralized error handling to eliminate code duplication across 4 functions - More robust exception handling with proper Google API types - Fixed regex pattern security issue with proper end anchoring Fix pre-commit validation issues: - Remove unused variables and parameters in ModelErrorDialog - Fix invalid JSON syntax in tsconfig files (remove comments) - Maintain all functionality while improving code quality All model validation tests continue to pass.
1 parent 85dd601 commit 5b9fa2f

File tree

12 files changed

+35
-63
lines changed

12 files changed

+35
-63
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,4 @@ repos:
7373

7474
# Global settings
7575
default_install_hook_types: [pre-commit]
76-
default_stages: [pre-commit]
76+
default_stages: [pre-commit]

backend/src/agent/graph.py

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22

33
from dotenv import load_dotenv
4+
from google.api_core import exceptions as google_exceptions
45
from google.genai import Client
56
from langchain_core.messages import AIMessage
67
from langchain_core.runnables import RunnableConfig
@@ -39,6 +40,16 @@
3940
genai_client = Client(api_key=os.getenv("GEMINI_API_KEY"))
4041

4142

43+
def _handle_model_not_found(e: Exception, model_name: str):
44+
"""Checks for a model not found error and raises a specific ValueError."""
45+
if isinstance(e, google_exceptions.NotFound) or (
46+
"404" in str(e) and "models/" in str(e)
47+
):
48+
error_msg = f"Model '{model_name}' not found. Please try a different model."
49+
raise ValueError(error_msg) from e
50+
raise e
51+
52+
4253
# Nodes
4354
def generate_query(state: OverallState, config: RunnableConfig) -> QueryGenerationState:
4455
"""LangGraph node that generates search queries based on the User's question.
@@ -83,15 +94,7 @@ def generate_query(state: OverallState, config: RunnableConfig) -> QueryGenerati
8394
result = structured_llm.invoke(formatted_prompt)
8495
return {"search_query": result.query}
8596
except Exception as e:
86-
# Check if this is a model not found error
87-
if "404" in str(e) and "models/" in str(e):
88-
# Return an error that the frontend can catch
89-
error_msg = (
90-
f"Model '{model_to_use}' not found. Please try a different model."
91-
)
92-
raise ValueError(error_msg) from e
93-
# Re-raise other errors
94-
raise
97+
_handle_model_not_found(e, model_to_use)
9598

9699

97100
def continue_to_web_research(state: QueryGenerationState):
@@ -154,15 +157,7 @@ def web_research(state: WebSearchState, config: RunnableConfig) -> OverallState:
154157
"web_research_result": [modified_text],
155158
}
156159
except Exception as e:
157-
# Check if this is a model not found error
158-
if "404" in str(e) and "models/" in str(e):
159-
# Return an error that the frontend can catch
160-
error_msg = (
161-
f"Model '{model_to_use}' not found. Please try a different model."
162-
)
163-
raise ValueError(error_msg) from e
164-
# Re-raise other errors
165-
raise
160+
_handle_model_not_found(e, model_to_use)
166161

167162

168163
def reflection(state: OverallState, config: RunnableConfig) -> ReflectionState:
@@ -209,15 +204,7 @@ def reflection(state: OverallState, config: RunnableConfig) -> ReflectionState:
209204
"number_of_ran_queries": len(state["search_query"]),
210205
}
211206
except Exception as e:
212-
# Check if this is a model not found error
213-
if "404" in str(e) and "models/" in str(e):
214-
# Return an error that the frontend can catch
215-
error_msg = (
216-
f"Model '{reasoning_model}' not found. Please try a different model."
217-
)
218-
raise ValueError(error_msg) from e
219-
# Re-raise other errors
220-
raise
207+
_handle_model_not_found(e, reasoning_model)
221208

222209

223210
def evaluate_research(
@@ -305,15 +292,7 @@ def finalize_answer(state: OverallState, config: RunnableConfig):
305292
"sources_gathered": unique_sources,
306293
}
307294
except Exception as e:
308-
# Check if this is a model not found error
309-
if "404" in str(e) and "models/" in str(e):
310-
# Return an error that the frontend can catch
311-
error_msg = (
312-
f"Model '{reasoning_model}' not found. Please try a different model."
313-
)
314-
raise ValueError(error_msg) from e
315-
# Re-raise other errors
316-
raise
295+
_handle_model_not_found(e, reasoning_model)
317296

318297

319298
# Create our Agent Graph

backend/tests/test_model_validation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def test_backend_models_follow_naming_convention(self):
7070
)
7171

7272
# Should follow gemini-X.Y-model pattern
73-
assert re.match(r"^gemini-\d+\.\d+-(flash|pro)(-lite)?", model), (
73+
assert re.match(r"^gemini-\d+\.\d+-(flash|pro)(-lite)?$", model), (
7474
f"Model {model} doesn't follow expected naming pattern"
7575
)
7676

frontend/.prettierignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ build/
44
.next/
55
coverage/
66
*.min.js
7-
*.min.css
7+
*.min.css

frontend/src/App.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ export default function App() {
7474
}
7575
},
7676
onError: (error: any) => {
77-
// Check if this is a model 404 error
78-
if (error.message && error.message.includes("404") && error.message.includes("models/")) {
79-
const modelMatch = error.message.match(/models\/([\w-]+)/);
77+
// Check if this is a model not found error using more specific matching
78+
if (error.message?.includes("not found. Please try a different model.")) {
79+
const modelMatch = error.message.match(/Model '([\w.-]+)' not found/);
8080
if (modelMatch && lastSubmission) {
8181
const failedModel = modelMatch[1];
8282
setModelError({
@@ -256,7 +256,6 @@ export default function App() {
256256
<ModelErrorDialog
257257
isOpen={!!modelError}
258258
failedModel={modelError?.failedModel || ""}
259-
errorMessage={modelError?.errorMessage || ""}
260259
onContinueWithFallback={handleModelErrorContinue}
261260
onRetryWithDifferent={handleModelErrorRetry}
262261
onClose={handleModelErrorClose}

frontend/src/components/ModelErrorDialog.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { AlertTriangle, Zap, Cpu, CheckCircle } from "lucide-react";
55
interface ModelErrorDialogProps {
66
isOpen: boolean;
77
failedModel: string;
8-
errorMessage: string;
98
onContinueWithFallback: (fallbackModel: string, rememberChoice: boolean) => void;
109
onRetryWithDifferent: (newModel: string, rememberChoice: boolean) => void;
1110
onClose: () => void;
@@ -14,16 +13,15 @@ interface ModelErrorDialogProps {
1413
export const ModelErrorDialog: React.FC<ModelErrorDialogProps> = ({
1514
isOpen,
1615
failedModel,
17-
errorMessage,
1816
onContinueWithFallback,
1917
onRetryWithDifferent,
2018
onClose,
2119
}) => {
22-
const [rememberChoice, setRememberChoice] = React.useState(false);
2320

2421
if (!isOpen) return null;
2522

26-
const recommendedFallback = "gemini-2.0-flash";
23+
const recommendedFallback =
24+
failedModel === "gemini-2.0-flash" ? "gemini-2.5-flash" : "gemini-2.0-flash";
2725

2826
return (
2927
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">

frontend/src/test/model-validation.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ describe("Model Error Handling", () => {
9292
const errorDialogPath = join(process.cwd(), "src", "components", "ModelErrorDialog.tsx");
9393
const source = readFileSync(errorDialogPath, "utf-8");
9494

95-
// Look for the recommended fallback model
96-
const fallbackMatch = source.match(/recommendedFallback = "([^"]+)"/);
95+
// Look for the dynamic fallback model logic
96+
const fallbackMatch = source.match(/recommendedFallback =\s*\n?\s*failedModel === "([^"]+)"/);
9797
expect(fallbackMatch).toBeTruthy();
9898

9999
if (fallbackMatch) {

frontend/tsconfig.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@
1010
"paths": {
1111
"@/*": ["./src/*"]
1212
},
13-
/* Bundler mode */
1413
"moduleResolution": "bundler",
1514
"allowImportingTsExtensions": true,
1615
"isolatedModules": true,
1716
"moduleDetection": "force",
1817
"noEmit": true,
1918
"jsx": "react-jsx",
20-
/* Linting */
2119
"strict": true,
2220
"noUnusedLocals": true,
2321
"noUnusedParameters": true,

frontend/tsconfig.node.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@
66
"module": "ESNext",
77
"skipLibCheck": true,
88

9-
/* Bundler mode */
109
"moduleResolution": "bundler",
1110
"allowImportingTsExtensions": true,
1211
"isolatedModules": true,
1312
"moduleDetection": "force",
1413
"noEmit": true,
1514

16-
/* Linting */
1715
"strict": true,
1816
"noUnusedLocals": true,
1917
"noUnusedParameters": true,

setup-precommit.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ echo "✅ Pre-commit setup complete!"
3030
echo ""
3131
echo "Pre-commit hooks will now run automatically before each commit."
3232
echo "To run manually: pre-commit run --all-files"
33-
echo "To skip hooks (emergency only): git commit --no-verify"
33+
echo "To skip hooks (emergency only): git commit --no-verify"

0 commit comments

Comments
 (0)