Skip to content

Fix avoid lint#178

Merged
galshubeli merged 2 commits intostagingfrom
fix-avoid-lint
Sep 2, 2025
Merged

Fix avoid lint#178
galshubeli merged 2 commits intostagingfrom
fix-avoid-lint

Conversation

@galshubeli
Copy link
Collaborator

@galshubeli galshubeli commented Sep 2, 2025

Summary by CodeRabbit

  • New Features

    • API Tokens: generate, view, and delete tokens from the profile.
    • Connect Database: guided, streaming setup for PostgreSQL/MySQL with real-time steps.
    • Optional MCP API surface for external tooling.
    • UI: new left-toolbar footer actions, Connect Database button, GitHub link, theme toggle.
  • Changes

    • Simplified OAuth flows; app now lands on chat (landing page removed).
    • Updated environment config (.env): FALKORDB_URL, FASTAPI_SECRET_KEY, email settings, analytics.
  • Documentation

    • README overhaul (Docker quickstart, REST/MCP docs); TOKEN_MANAGEMENT.md added.
  • Tests

    • Revamped E2E flows and fixtures.
  • Chores

    • CI triggers use staging; dependency and build tweaks.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 2, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This PR introduces MCP endpoints and token management, converts database connection and chat flows to streaming, refactors loaders to async generators with distinct-value extraction, updates auth flows (OAuth + API tokens), revises config/env variables, removes legacy loaders/examples/validators, updates frontend UI/TS for connect + tokens, and adjusts tests/CI to new flows.

Changes

Cohort / File(s) Summary
Env & Docs
/.env.example, /README.md, /.github/copilot-instructions.md, /.github/wordlist.txt, /TOKEN_MANAGEMENT.md
Reorganized env (FASTAPI_SECRET_KEY, FALKORDB_URL, email/OAuth vars), added MCP and token docs, expanded README (quickstart, MCP, REST/API), added terms to wordlist, introduced token management spec.
CI/CD & Pytest
.github/workflows/e2e-tests.yml, .github/workflows/tests.yml, /pytest.ini
Switched workflow branches to main+staging, decoupled e2e from unit-tests, relaxed Playwright addopts (no forced browser/headed).
Build & Deps
/Makefile, /Pipfile, /.gitignore
NPM install uses --prefix, added fastapi-mcp and bumped litellm, ignored demo_tokens.py.
App/Auth/Config
/api/app_factory.py, /api/auth/oauth_handlers.py, /api/auth/user_management.py, /api/config.py
Mounted MCP (toggle via DISABLE_MCP), added /tokens router, refactored user management (API tokens, input validation), adjusted OAuth handlers, provider-driven model selection in Config and new DB thresholds.
Memory
/api/memory/graphiti_tool.py, /api/memory/__init__.py
Added Azure/OpenAI branching for Graphiti client; prompt tweaks; minimized per-instance config.
Agents
/api/agents/analysis_agent.py, /api/agents/follow_up_agent.py, /api/agents/relevancy_agent.py, /api/agents/utils.py, /api/agents/__init__.py, …taxonomy_agent.py
Typing/lint refactors, removed TaxonomyAgent (file and re-export), streamlined prompts/handling; formatting only in relevancy; base lint directive.
Loaders Core
/api/loaders/base_loader.py, /api/loaders/mysql_loader.py, /api/loaders/postgres_loader.py, /api/loaders/graph_loader.py, /api/loaders/__init__.py, …csv_loader.py, …json_loader.py, …odata_loader.py, …schema_validator.py
Converted loaders to async generators with progress yielding; added distinct-value extraction helpers; added specialized exceptions; expanded schema-affecting SQL patterns; removed CSV/JSON/OData loaders and schema validator.
Routes & Streaming
/api/routes/database.py, /api/routes/graphs.py, /api/routes/auth.py, /api/routes/__init__.py, /api/routes/tokens.py
/database streams delimited JSON progress; graphs endpoints updated (streaming query/confirm flows, schema handling); auth routes simplified and Google/GitHub flows updated; added tokens CRUD endpoints; annotated operation_ids.
Backend Removals/Refactors
/api/constants.py, /api/helpers/crm_data_generator.py, /api/schema_aba.json, /api/schema_schema.json, /api/utils.py, /api/graph.py
Removed constants, CRM generator, JSON Schemas; trimmed utils to generate_db_description; minor typing/logging tweaks in graph.find.
Frontend CSS/Templates
/app/public/css/*, /app/templates/*, /app/templates/components/*
Removed landing page/styles; added token modal and connect workflow UI (custom dropdown, steps); toolbar/footer buttons; header “Connect Database” button; profile actions updated; new/updated selectors and responsive rules.
Frontend TS
/app/ts/app.ts, /app/ts/modules/modals.ts, /app/ts/modules/tokens.ts, /app/ts/modules/ui.ts
Initialized token management; refactored database modal to streaming connect with multi-trigger and steps; added tokens module (list/generate/delete/copy); stricter dropdown DOM assumptions.
Tests
/tests/conftest.py, /tests/e2e/**/*, /tests/test_mysql_loader.py, /tests/test_postgres_loader.py, /tests/e2e/README.md
New e2e marker/fixtures with dev auth bypass; updated navigation waits; added unauthenticated flow tests; expanded file upload tests; adjusted loader tests to consume async generators.
Examples & Deployment
/examples/*, /vercel.json
Removed multiple example schemas/SQL/data files and Vercel config.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User (UI)
  participant FE as Frontend (TS)
  participant BE as FastAPI /database
  participant L as Loader (Postgres/MySQL)
  Note over U,FE: Connect Database (streaming)
  U->>FE: Click "Connect Database"
  FE->>BE: POST /database {url,type}
  activate BE
  BE-->>FE: stream: reasoning_step("Starting…")
  BE->>L: loader.load(url) (async generator)
  loop Progress
    L-->>BE: yield (ok,msg)
    BE-->>FE: stream: reasoning_step(msg)
  end
  alt success
    L-->>BE: final (True, "Loaded")
    BE-->>FE: stream: final_result(success)
  else error
    L-->>BE: final (False, err)
    BE-->>FE: stream: error(err)
  end
  deactivate BE
  FE->>FE: Update steps UI / reload on success
Loading
sequenceDiagram
  autonumber
  participant U as User
  participant FE as Frontend
  participant BE as FastAPI /login/*
  participant OA as OAuth Provider
  participant UM as User Mgmt
  Note over U,FE: OAuth login issuing API token
  U->>FE: Click Login (Google/GitHub)
  FE->>BE: GET /login/{provider}
  BE->>OA: Redirect to provider auth
  OA->>BE: Callback with code
  BE->>OA: Exchange code for token
  OA-->>BE: Access token
  BE->>OA: Fetch userinfo
  OA-->>BE: User profile
  BE->>UM: ensure_user_in_organizations(user)
  UM-->>BE: user stored
  BE->>BE: callback_handler → issue api_token
  BE-->>FE: Redirect "/" + Set-Cookie(api_token)
  FE->>U: Authenticated session
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • gkorland

Poem

A carrot of configs, a stream of delight,
I toggled MCP under moonlit night.
Tokens I minted, with hops and with cheer,
Connect to your data—step by step, near.
OAuth’s a warren, but cookies are sweet—
QueryWeaver’s ready; thump-thump… execute! 🥕🐇

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-avoid-lint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link

github-actions bot commented Sep 2, 2025

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 5 package(s) with unknown licenses.
  • ⚠️ 1 packages with OpenSSF Scorecard issues.
See the Details below.

License Issues

Pipfile

PackageVersionLicenseIssue Type
fastapi-mcp~> 0.4.0NullUnknown License
litellm~> 1.76.0NullUnknown License

Pipfile.lock

PackageVersionLicenseIssue Type
regex2025.8.29NullUnknown License
litellm1.76.1NullUnknown License
mcp1.13.1NullUnknown License

OpenSSF Scorecard

Scorecard details
PackageVersionScoreDetails
pip/fastapi-mcp ~> 0.4.0 UnknownUnknown
pip/litellm ~> 1.76.0 UnknownUnknown
pip/authlib 1.6.3 UnknownUnknown
pip/fastapi-mcp 0.4.0 UnknownUnknown
pip/fastuuid 0.12.0 UnknownUnknown
pip/httpx-sse 0.4.1 UnknownUnknown
pip/litellm 1.76.1 UnknownUnknown
pip/markdown-it-py 4.0.0 🟢 6.5
Details
CheckScoreReason
Maintained🟢 1010 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 10
Code-Review🟢 3Found 8/23 approved changesets -- score normalized to 3
Security-Policy🟢 10security policy file detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Binary-Artifacts🟢 10no binaries found in the repo
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Fuzzing🟢 10project is fuzzed
Vulnerabilities🟢 100 existing vulnerabilities detected
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/mcp 1.13.1 UnknownUnknown
pip/mdurl 0.1.2 🟢 4
Details
CheckScoreReason
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Maintained⚠️ 00 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Code-Review⚠️ 0Found 2/26 approved changesets -- score normalized to 0
Packaging⚠️ -1packaging workflow not detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Binary-Artifacts🟢 10no binaries found in the repo
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
License🟢 9license file detected
Fuzzing🟢 10project is fuzzed
Vulnerabilities🟢 100 existing vulnerabilities detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
Security-Policy⚠️ 0security policy file not detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/pydantic-settings 2.10.1 ⚠️ 1.3
Details
CheckScoreReason
Code-Review⚠️ 0Found 0/30 approved changesets -- score normalized to 0
Maintained⚠️ 00 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Packaging⚠️ -1packaging workflow not detected
Pinned-Dependencies⚠️ -1no dependencies found
Token-Permissions⚠️ -1No tokens found
Dangerous-Workflow⚠️ -1no workflows found
Binary-Artifacts🟢 10no binaries found in the repo
SAST⚠️ 0no SAST tool detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Security-Policy⚠️ 0security policy file not detected
License⚠️ 0license file not detected
Fuzzing⚠️ 0project is not fuzzed
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
Vulnerabilities⚠️ 027 existing vulnerabilities detected
pip/pygments 2.19.2 🟢 6.5
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 4 issue activity found in the last 90 days -- score normalized to 10
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
Code-Review🟢 6Found 12/18 approved changesets -- score normalized to 6
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
License🟢 10license file detected
Security-Policy⚠️ 0security policy file not detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
Signed-Releases⚠️ -1no releases found
Vulnerabilities🟢 100 existing vulnerabilities detected
Binary-Artifacts🟢 10no binaries found in the repo
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
Fuzzing🟢 10project is fuzzed
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
pip/regex 2025.8.29 UnknownUnknown
pip/rich 14.1.0 🟢 7.1
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 8 issue activity found in the last 90 days -- score normalized to 10
Security-Policy🟢 10security policy file detected
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Code-Review⚠️ 2Found 4/17 approved changesets -- score normalized to 2
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Binary-Artifacts🟢 10no binaries found in the repo
License🟢 10license file detected
Fuzzing🟢 10project is fuzzed
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Signed-Releases⚠️ -1no releases found
Pinned-Dependencies⚠️ 2dependency not pinned by hash detected -- score normalized to 2
Vulnerabilities🟢 91 existing vulnerabilities detected
SAST🟢 9SAST tool detected but not run on all commits
pip/shellingham 1.5.4 🟢 3
Details
CheckScoreReason
Code-Review🟢 5Found 6/11 approved changesets -- score normalized to 5
Maintained⚠️ 00 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Security-Policy⚠️ 0security policy file not detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Packaging⚠️ -1packaging workflow not detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
Vulnerabilities⚠️ 013 existing vulnerabilities detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/sse-starlette 3.0.2 🟢 4.6
Details
CheckScoreReason
Maintained🟢 1016 commit(s) and 7 issue activity found in the last 90 days -- score normalized to 10
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Code-Review⚠️ 2Found 5/23 approved changesets -- score normalized to 2
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Binary-Artifacts🟢 10no binaries found in the repo
Security-Policy⚠️ 0security policy file not detected
License🟢 10license file detected
Vulnerabilities🟢 100 existing vulnerabilities detected
Fuzzing⚠️ 0project is not fuzzed
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/tokenizers 0.22.0 🟢 5.3
Details
CheckScoreReason
Maintained🟢 1018 commit(s) and 15 issue activity found in the last 90 days -- score normalized to 10
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Code-Review🟢 7Found 20/26 approved changesets -- score normalized to 7
Security-Policy⚠️ 0security policy file not detected
License🟢 10license file detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Binary-Artifacts🟢 10no binaries found in the repo
Fuzzing⚠️ 0project is not fuzzed
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Signed-Releases⚠️ -1no releases found
Packaging🟢 10packaging workflow detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
Vulnerabilities🟢 46 existing vulnerabilities detected
pip/tomli 2.2.1 🟢 4.7
Details
CheckScoreReason
Code-Review🟢 3Found 7/21 approved changesets -- score normalized to 3
Maintained⚠️ 01 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Binary-Artifacts🟢 10no binaries found in the repo
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Security-Policy⚠️ 0security policy file not detected
Fuzzing🟢 10project is fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Vulnerabilities🟢 91 existing vulnerabilities detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/typer 0.17.3 UnknownUnknown

Scanned Files

  • Pipfile
  • Pipfile.lock

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 27

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (17)
api/agents/relevancy_agent.py (1)

74-89: Async method calls a blocking client; switch to async to avoid event-loop blocking

completion(...) is synchronous. In an async FastAPI context this can block workers under load.

Apply:

-from litellm import completion
+from litellm import acompletion
@@
-        completion_result = completion(
+        completion_result = await acompletion(
             model=Config.COMPLETION_MODEL,
             messages=self.messages,
             temperature=0,
         )

If keeping the sync client is required, wrap with anyio.to_thread.run_sync(...) instead.

.github/workflows/e2e-tests.yml (1)

58-60: Wrong env var names: using FLASK_ in a FastAPI app will cause misconfiguration*

Docs and code use FASTAPI_; E2E may not boot with FLASK_.

Apply:

-        echo "FLASK_SECRET_KEY=test-secret-key-for-ci" >> .env
-        echo "FLASK_DEBUG=False" >> .env
+        echo "FASTAPI_SECRET_KEY=test-secret-key-for-ci" >> .env
+        echo "FASTAPI_DEBUG=False" >> .env
+        echo "APP_ENV=ci" >> .env
tests/e2e/README.md (1)

1-238: Fix CI spellcheck failure in root README.md

Spellcheck reports a misspelling: “”. Replace with “HTML content” (and avoid angle brackets which look like tags) or add a dictionary whitelist if intentional.

Happy to open a follow-up PR to patch README.md to unblock CI.

api/graph.py (2)

304-310: Bug: results unpacking drops column-only results.

When only column_embeddings exist, results[0] is ignored and nothing is returned.

Apply:

-    # Unpack results based on what tasks we ran
-    tables_des = results[0] if table_embeddings else []
-    tables_by_columns_des = results[1] if (table_embeddings and column_embeddings) else []
+    # Unpack results based on what tasks we ran
+    if table_embeddings and column_embeddings:
+        tables_des = results[0]
+        tables_by_columns_des = results[1]
+    elif table_embeddings:
+        tables_des = results[0]
+        tables_by_columns_des = []
+    elif column_embeddings:
+        tables_des = []
+        tables_by_columns_des = results[0]
+    else:
+        tables_des = []
+        tables_by_columns_des = []

257-260: Guard against empty queries_history to avoid IndexError.

Calling queries_history[-1] with an empty list will crash.

Apply:

-    graph = db.select_graph(graph_id)
-    user_query = queries_history[-1]
-    previous_queries = queries_history[:-1]
+    if not queries_history:
+        return []
+    graph = db.select_graph(graph_id)
+    user_query = queries_history[-1]
+    previous_queries = queries_history[:-1]
api/memory/graphiti_tool.py (3)

51-55: Vector index creation is not idempotent; repeated runs can fail.

Guard the CREATE with an existence check or swallow the “already exists” error so factory init is safe.

Apply this diff:

-        vector_size = Config.EMBEDDING_MODEL.get_vector_size()
-        driver = self.graphiti_client.driver
-        await driver.execute_query(f"CREATE VECTOR INDEX FOR (p:Query) ON (p.embeddings) OPTIONS {{dimension:{vector_size}, similarityFunction:'euclidean'}}")
+        vector_size = Config.EMBEDDING_MODEL.get_vector_size()
+        driver = self.graphiti_client.driver
+        try:
+            await driver.execute_query(
+                f"CREATE VECTOR INDEX FOR (p:Query) ON (p.embeddings) "
+                f"OPTIONS {{dimension:{vector_size}, similarityFunction:'euclidean'}}"
+            )
+        except Exception as e:
+            # tolerate re-creation attempts
+            if "already exists" not in str(e).lower():
+                raise

201-246: Cypher injection risk and brittle escaping; parameterize queries.

Manual quote-escaping is error-prone. Use Cypher parameters for user/sql/error strings and rely on MERGE to dedupe.

Apply this diff:

-            # Check if Query node with same user_query and sql_query already exists
-            relationship_type = "SUCCESS" if success else "FAILED"
-            
-            # Escape quotes in the query and SQL for Cypher
-            escaped_query = query.replace("'", "\\'").replace('"', '\\"')
-            escaped_sql = sql_query.replace("'", "\\'").replace('"', '\\"')
-            escaped_error = error.replace("'", "\\'").replace('"', '\\"') if error else ""
-            embeddings = Config.EMBEDDING_MODEL.embed(escaped_query)[0]
+            # Check if Query node with same user_query and sql_query already exists
+            relationship_type = "SUCCESS" if success else "FAILED"
+            embeddings = Config.EMBEDDING_MODEL.embed(query)[0]
@@
-            check_query = f"""
-            MATCH (db:Entity {{uuid: "{database_node_uuid}"}})
-            MATCH (db)-[r]->(q:Query)
-            WHERE q.user_query = "{escaped_query}" AND q.sql_query = "{escaped_sql}"
-            RETURN q.uuid as existing_query_uuid
-            LIMIT 1
-            """
+            check_query = """
+            MATCH (db:Entity {uuid: $database_node_uuid})-[]->(q:Query)
+            WHERE q.user_query = $user_query AND q.sql_query = $sql_query
+            RETURN q.uuid as existing_query_uuid
+            LIMIT 1
+            """
@@
-            check_result = await graph_driver.execute_query(check_query)
+            records, _, _ = await graph_driver.execute_query(
+                check_query,
+                database_node_uuid=database_node_uuid,
+                user_query=query,
+                sql_query=sql_query,
+            )
@@
-            if check_result[0]:  # If records exist
+            if records:  # If records exist
                 print(f"Query with same user_query and sql_query already exists, skipping creation")
                 return True
@@
-            cypher_query = f"""
-            MATCH (db:Entity {{uuid: "{database_node_uuid}"}})
-            MERGE (q:Query {{
-                user_query: "{escaped_query}",
-                sql_query: "{escaped_sql}",
-                success: {str(success).lower()},
-                error: "{escaped_error}",
-                timestamp: timestamp(),
-                embeddings: vecf32($embedding)
-            }})
-            CREATE (db)-[:{relationship_type} {{timestamp: timestamp()}}]->(q)
-            RETURN q.uuid as query_uuid
-            """
+            cypher_query = f"""
+            MATCH (db:Entity {{uuid: $database_node_uuid}})
+            MERGE (q:Query {{
+                user_query: $user_query,
+                sql_query: $sql_query
+            }})
+            SET q.success = $success,
+                q.error = coalesce($error, ""),
+                q.timestamp = timestamp(),
+                q.embeddings = vecf32($embedding)
+            CREATE (db)-[:{relationship_type} {{timestamp: timestamp()}}]->(q)
+            RETURN q.uuid as query_uuid
+            """
@@
-                result = await graph_driver.execute_query(cypher_query, embedding=embeddings)
+                await graph_driver.execute_query(
+                    cypher_query,
+                    database_node_uuid=database_node_uuid,
+                    user_query=query,
+                    sql_query=sql_query,
+                    success=bool(success),
+                    error=error,
+                    embedding=embeddings,
+                )
                 return True

Also applies to: 229-240, 205-209


26-26: Avoid blocking the event loop; use litellm’s async client.

summarize_conversation is async but uses the sync completion(); switch to acompletion().

Apply this diff:

-from litellm import completion
+from litellm import acompletion
-            response = completion(
+            response = await acompletion(
                 model=Config.COMPLETION_MODEL,
                 messages=[{"role": "user", "content": prompt}],
                 temperature=0.1
             )

Also applies to: 571-575

api/loaders/postgres_loader.py (1)

453-459: Bug: awaiting an async generator returns a generator object, not (success, message)

PostgresLoader.load is an async generator. You must consume it and use the last tuple. Current code will raise TypeError and never refresh.

-            # Reuse the existing load method to reload the schema
-            success, message = await PostgresLoader.load(prefix, db_url)
-
-            if success:
-                logging.info("Graph schema refreshed successfully.")
-                return True, message
-
-            logging.error("Schema refresh failed")
-            return False, "Failed to reload schema"
+            # Reuse the existing load method to reload the schema (consume async generator)
+            last_success, last_message = False, "No progress emitted"
+            async for success, message in PostgresLoader.load(prefix, db_url):
+                last_success, last_message = success, message
+
+            if last_success:
+                logging.info("Graph schema refreshed successfully.")
+                return True, last_message
+
+            logging.error("Schema refresh failed")
+            return False, "Failed to reload schema"
tests/e2e/test_basic_functionality.py (1)

1-3: Silence Ruff S101 for pytest asserts

Keep idiomatic pytest asserts without lint noise.

+ # ruff: noqa: S101  # Allow `assert` in tests
 """
 Test basic application functionality.
 """
api/app_factory.py (1)

105-119: Don’t swallow HTTPException; also fix Ruff ARG001 by marking request unused.

Reorder the checks so HTTPException is re-raised first, and rename the unused param to _request to satisfy Ruff.

Apply:

-    async def handle_oauth_error(request: Request, exc: Exception): # pylint: disable=unused-argument
+    async def handle_oauth_error(_request: Request, exc: Exception):
         """Handle OAuth-related errors gracefully"""
-        # Check if it's an OAuth-related error
-        # TODO check this scenario, pylint: disable=fixme
-        if "token" in str(exc).lower() or "oauth" in str(exc).lower():
-            logging.warning("OAuth error occurred: %s", exc)
-            return RedirectResponse(url="/", status_code=302)
-
-        # If it's an HTTPException, re-raise so FastAPI handles it properly
-        if isinstance(exc, HTTPException):
-            raise exc
+        # If it's an HTTPException, re-raise so FastAPI handles it properly
+        if isinstance(exc, HTTPException):
+            raise exc
+        # Best-effort OAuth error handling
+        if "token" in str(exc).lower() or "oauth" in str(exc).lower():
+            logging.warning("OAuth error occurred: %s", exc)
+            return RedirectResponse(url="/", status_code=302)
api/routes/auth.py (1)

128-135: Guard against missing email to prevent downstream auth failures.

token_required encodes email; missing email will 401 after setting a cookie. Fail early or derive a stable identifier.

         if user_info:
             user_data = {
                 'id': user_info.get('id') or user_info.get('sub'),
                 'email': user_info.get('email'),
                 'name': user_info.get('name'),
                 'picture': user_info.get('picture'),
             }
+            if not user_data['email']:
+                logging.warning("Google user is missing email; refusing login")
+                raise HTTPException(status_code=400, detail="Email is required for authentication")
@@
         if user_info:
             user_data = {
                 'id': user_info.get('id'),
                 'email': email,
                 'name': user_info.get('name'),
                 'picture': user_info.get('avatar_url'),
             }
+            if not user_data['email']:
+                logging.warning("GitHub user is missing email; refusing login")
+                raise HTTPException(status_code=400, detail="Email is required for authentication")

Also applies to: 219-226

api/loaders/mysql_loader.py (3)

175-212: Ensure connection/cursor are closed on all paths; log with stack traces.

Current path closes only on success. On exceptions, resources can leak; also prefer logging.exception per TRY400.

Apply:

-        try:
+        conn = None
+        cursor = None
+        try:
             # Parse connection URL
             conn_params = MySQLLoader._parse_mysql_url(connection_url)

             # Connect to MySQL database
-            conn = pymysql.connect(**conn_params)
-            cursor = conn.cursor(DictCursor)
+            conn = pymysql.connect(**conn_params)
+            cursor = conn.cursor(DictCursor)
@@
-            # Close database connection
-            cursor.close()
-            conn.close()
+            # (closed in finally)
@@
-        except pymysql.MySQLError as e:
-            logging.error("MySQL connection error: %s", e)
-            yield False, f"MySQL connection error: {str(e)}"
-        except Exception as e:  # pylint: disable=broad-exception-caught
-            logging.error("Error loading MySQL schema: %s", e)
-            yield False, f"Error loading MySQL schema: {str(e)}"
+        except pymysql.MySQLError as e:
+            logging.exception("MySQL connection error")
+            yield False, f"MySQL connection error: {e!s}"
+        except Exception as e:  # pylint: disable=broad-exception-caught
+            logging.exception("Error loading MySQL schema")
+            yield False, f"Error loading MySQL schema: {e!s}"
+        finally:
+            try:
+                if cursor is not None:
+                    cursor.close()
+            except Exception:  # best-effort
+                pass
+            try:
+                if conn is not None:
+                    conn.close()
+            except Exception:
+                pass

486-494: Bug: treating async generator as awaitable.

MySQLLoader.load() yields; you must consume it to get the final status/message.

Apply:

-            success, message = await MySQLLoader.load(prefix, db_url)
-
-            if success:
-                logging.info("Graph schema refreshed successfully.")
-                return True, message
-
-            logging.error("Schema refresh failed")
-            return False, "Failed to reload schema"
+            success = False
+            message = ""
+            async for success, message in MySQLLoader.load(prefix, db_url):
+                pass
+            if success:
+                logging.info("Graph schema refreshed successfully.")
+                return True, message
+            else:
+                logging.error("Schema refresh failed")
+                return False, "Failed to reload schema"

566-574: Exception paths can raise UnboundLocalError; include stack traces.

cursor may be undefined when only conn exists. Also prefer logging.exception.

Apply:

-        except pymysql.MySQLError as e:
-            # Rollback in case of error
-            if 'conn' in locals():
-                conn.rollback()
-                cursor.close()
-                conn.close()
-            logging.error("MySQL query execution error: %s", e)
-            raise MySQLQueryError(f"MySQL query execution error: {str(e)}") from e
+        except pymysql.MySQLError as e:
+            if 'conn' in locals():
+                try:
+                    conn.rollback()
+                except Exception:
+                    pass
+                try:
+                    if 'cursor' in locals():
+                        cursor.close()
+                except Exception:
+                    pass
+                try:
+                    conn.close()
+                except Exception:
+                    pass
+            logging.exception("MySQL query execution error")
+            raise MySQLQueryError(f"MySQL query execution error: {e!s}") from e
-        except Exception as e:
-            # Rollback in case of error
-            if 'conn' in locals():
-                conn.rollback()
-                cursor.close()
-                conn.close()
-            logging.error("Error executing SQL query: %s", e)
-            raise MySQLQueryError(f"Error executing SQL query: {str(e)}") from e
+        except Exception as e:
+            if 'conn' in locals():
+                try:
+                    conn.rollback()
+                except Exception:
+                    pass
+                try:
+                    if 'cursor' in locals():
+                        cursor.close()
+                except Exception:
+                    pass
+                try:
+                    conn.close()
+                except Exception:
+                    pass
+            logging.exception("Error executing SQL query")
+            raise MySQLQueryError(f"Error executing SQL query: {e!s}") from e

Also applies to: 580-581

app/public/css/menu.css (1)

208-214: Scope dropdown styles to a dedicated class
.header-button is used globally (e.g. the “Connect Database” button in app/templates/components/chat_header.j2), so redefining it in app/public/css/menu.css (lines 208–214) will impact all header buttons. Rename this rule to a specific container class:

-.header-button {
+.custom-dropdown {
   position: relative;
   display: inline-block;
   min-width: 140px;
}
api/agents/analysis_agent.py (1)

24-33: Add unit tests for parse_response missing keys
Ensure parse_response always returns "sql_query", "ambiguities", and "missing_information" and add tests covering cases where fields are absent or JSON parsing falls back.

@galshubeli galshubeli changed the base branch from main to staging September 2, 2025 10:13
@galshubeli galshubeli requested a review from Copilot September 2, 2025 10:15
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR addresses pylint warnings by adding appropriate disable comments throughout the codebase to suppress specific lint violations that are acceptable for test files and specific use cases.

Key changes:

  • Added pylint disable comments for commonly accepted violations in test files (line-too-long, broad-exception-caught)
  • Resolved unused variable warnings by replacing unused assignments with underscore variables
  • Added disable comments for specific pylint rules where the code pattern is intentional

Reviewed Changes

Copilot reviewed 18 out of 20 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/test_mysql_loader.py Added protected-access disable for test accessing private methods
tests/e2e/test_unauthenticated_flow.py Removed unused import, added line-too-long disables, replaced unused variable
tests/e2e/test_file_upload.py Added multiple pylint disables for test-specific patterns
tests/e2e/test_basic_functionality.py Added line-too-long disable and replaced unused variables
tests/e2e/test_api_endpoints.py Added unused-argument and line-too-long disables
tests/e2e/pages/home_page.py Added broad-exception-caught and broad-exception-raised disables
tests/e2e/pages/base_page.py Moved inline comment to separate line for better readability
tests/e2e/fixtures/test_data.py Added consider-using-with disable for test fixture
tests/e2e/examples/dev_auth_bypass.py Added imports and disable comments for development example
tests/conftest.py Added multiple pylint disables for test configuration patterns
api/routes/tokens.py Added line-too-long disables for logging statements
api/routes/graphs.py Multiple fixes including unused variables, function signature disables
api/memory/graphiti_tool.py Added disable=all for external integration
api/graph.py Added too-many-locals disable for complex function
api/auth/user_management.py Added too-many-positional-arguments disable
api/auth/oauth_handlers.py Added broad-exception-caught disable with explanatory comment
api/app_factory.py Added various disables for middleware and exception handler patterns
.github/wordlist.txt Added "OpenAI's" to spell check whitelist

@galshubeli galshubeli merged commit 9a2107b into staging Sep 2, 2025
9 checks passed
@galshubeli galshubeli deleted the fix-avoid-lint branch September 2, 2025 10:18
@coderabbitai coderabbitai bot mentioned this pull request Sep 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant