Skip to content

Wegent db session lifetime fixes - #1330

Merged
feifei325 merged 6 commits into
wecode-ai:mainfrom
feifei325:wegent-db-session-lifetime-fixes
Jun 10, 2026
Merged

feifei325 merged 6 commits into
wecode-ai:mainfrom
feifei325:wegent-db-session-lifetime-fixes

Conversation

@feifei325

@feifei325 feifei325 commented Jun 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Bug Fixes

    • Prevented database session leaks and race conditions across background tasks, document indexing, repository updates, remote gateway calls, and subscription dispatches.
  • Refactor

    • Background processing, indexing, repository-job, and subscription flows now use short-lived/session-managed lifecycles for more reliable async and external-gateway interactions.
  • Tests

    • Expanded coverage confirming sessions are closed before external calls, plus additional unit, async, and e2e tests for summary/indexing and scheduler behavior.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ae64b1af-b851-4f14-9cfc-48f152239a51

📥 Commits

Reviewing files that changed from the base of the PR and between bfd9742 and c45f472.

📒 Files selected for processing (1)
  • frontend/e2e/tests/code-task.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/e2e/tests/code-task.spec.ts

📝 Walkthrough

Walkthrough

This PR refactors many services to use optional/owned DB sessions and short-lived session factories so sessions are created and closed around preparation/record work and closed before downstream async/gateway calls; matching tests and e2e fixture provisioning were added/updated.

Changes

Session Lifecycle Decoupling and Short-Session Pattern Rollout

Layer / File(s) Summary
RAG Gateway Protocol and Signature Updates
backend/app/services/rag/gateway.py, backend/app/services/rag/local_gateway.py, backend/app/services/rag/remote_gateway.py
RagGateway protocol's delete_document_index and gateway methods accept optional db: Session | None = None; gateways forward/own sessions and remote gateway can create a SessionLocal() when needed.
BackgroundChatExecutor Short-Session Pattern
backend/app/services/background_chat_executor.py
Constructor now accepts optional db and session_factory; added with_managed_sessions() and _execute_with_managed_sessions() to create short-lived sessions for task/subtask creation and final persistence, with centralized load/mark-complete/mark-failed helpers.
RAG Local Data Plane Session Management
backend/app/services/rag/local_data_plane/indexing.py
index_document_local can create/own a DB session, rolls back/closes before downstream async work, defers attachment binary loading when appropriate, and introduces dataclasses for preparation/deferred-source modeling.
RAG Gateway Implementations Using Optional Sessions
backend/app/services/rag/local_gateway.py, backend/app/services/rag/remote_gateway.py
LocalRagGateway forwards db=None to executors; RemoteRagGateway encapsulates request building and creates/cleans up a SessionLocal() when the caller omits db.
Knowledge Service Document Indexing: Prepare/Execute Split
backend/app/services/knowledge/indexing.py
run_document_indexing splits into _prepare_indexing_runtime (with its own DB session) and _run_indexing_gateway_calls (dedicated event loop); preparation returns structured skip/delete specs and resolved KB info.
Knowledge Service KB Summary: Claim/Execute/Write Split
backend/app/services/knowledge/summary_service.py
trigger_kb_summary uses _claim_kb_summary_generation to lock/claim and return KbSummaryClaim, then runs _execute_kb_summary_model via BackgroundChatExecutor.with_managed_sessions, and persists results via extracted write/failure helpers.
Repository Job: Snapshot-Based Session Decoupling
backend/app/services/repository_job.py, backend/app/services/jobs.py
Adds RepositoryUserSnapshot and load_repository_user_snapshots; update_repositories_for_all_users accepts a db_factory, materializes snapshots inside a loader session, closes it, then processes snapshots asynchronously; worker stops passing a sync session.
Subscription Scheduler: Keyset Pagination and Dispatch Extraction
backend/app/tasks/subscription_tasks.py
Async and sync schedulers iterate active subscriptions by keyset-batched ID pages and extract _load_active_subscription, _disable_expired_subscription_if_needed, and _dispatch_due_subscription to centralize per-subscription logic and failure handling.
Tests: BackgroundChatExecutor, Knowledge Services, RAG, Repository Job, Subscription Tasks
backend/tests/...
New and updated tests assert owned DB sessions are closed before downstream async operations (SSE collect, engine indexing, HTTP calls), adapt mocks to with_managed_sessions usage, and verify keyset pagination and dispatch failure behaviors.
Frontend e2e: Code Task fixture provisioning
frontend/e2e/tests/code-task.spec.ts
E2E suite provisions bot and team via API in beforeAll/afterAll, computes team-scoped code page route, and updates navigation and message-input locators accordingly.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

"I hopped through sessions, short and neat,
Closed each gate before the async beat,
Snapshots saved, gateways bowed, tests all sing,
A rabbit’s nod to tidy DBing." 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Wegent db session lifetime fixes' directly addresses the core objective of the changeset: refactoring database session management across multiple services to properly handle session lifecycles.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
backend/app/services/background_chat_executor.py (1)

387-391: 💤 Low value

Consider logging swallowed exceptions for observability.

The try-except-pass pattern is intentional since errors are handled via the emitter, but a debug log would aid troubleshooting without changing behavior.

🔧 Suggested improvement
         try:
             await dispatch_task
-        except Exception:
-            pass
+        except Exception:
+            logger.debug(
+                "[BackgroundChatExecutor] dispatch_task exception (handled via emitter)",
+                exc_info=True,
+            )
         return accumulated_content
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/background_chat_executor.py` around lines 387 - 391, The
except block that currently swallows exceptions when awaiting dispatch_task
should log the caught exception for observability without changing behavior;
update the except Exception: clause in background_chat_executor.py (the block
awaiting dispatch_task) to call the existing logger (or add one) and emit a
debug/exception-level log including the exception details and context (e.g.,
mention dispatch_task and accumulated_content or the related emitter) before
returning accumulated_content so the runtime behavior is unchanged but errors
are visible in logs.

Source: Linters/SAST tools

backend/app/services/repository_job.py (2)

211-277: 💤 Low value

Outdated docstrings reference User instead of RepositoryUserSnapshot.

The docstrings in helper methods still say "User object" but now accept RepositoryUserSnapshot.

Suggested fix for all four methods
     async def _update_github_repositories(
         self, user: RepositoryUserSnapshot, git_token: str, git_domain: str
     ) -> None:
         """
         Update GitHub repositories cache for a user

         Args:
-            user: User object
+            user: User snapshot
             git_token: GitHub token
             git_domain: GitHub domain
         """

Apply similarly to _update_gitlab_repositories, _update_gitee_repositories, and _update_gitea_repositories.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/repository_job.py` around lines 211 - 277, Docstrings
for _update_github_repositories, _update_gitlab_repositories,
_update_gitee_repositories, and _update_gitea_repositories incorrectly refer to
the parameter as "User object"; update each method's docstring to reference
RepositoryUserSnapshot (e.g., change "User object" to "RepositoryUserSnapshot")
and optionally add a brief description matching the type, ensuring the Args
section lists user: RepositoryUserSnapshot for _update_github_repositories,
_update_gitlab_repositories, _update_gitee_repositories, and
_update_gitea_repositories.

75-75: ⚡ Quick win

Remove extraneous f-string prefix.

The f-string has no placeholders.

Suggested fix
-            logger.info(f"[repository_job] Starting get all users task")
+            logger.info("[repository_job] Starting get all users task")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/repository_job.py` at line 75, The log call uses an
unnecessary f-string with no placeholders; replace the f-string in the
logger.info call (the line logging "[repository_job] Starting get all users
task" inside repository_job / the get-all-users task) with a plain string
literal (remove the leading f) so it’s a normal string instead of an f-string.

Source: Linters/SAST tools

backend/tests/tasks/test_subscription_tasks_legacy_trigger.py (1)

46-68: 💤 Low value

Remove unused _RecordingSubscriptionQuery class.

This class is defined but never used in the test file. Only _RecordingKeysetSubscriptionQuery is used in the pagination tests. Consider removing it to avoid dead code.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/tests/tasks/test_subscription_tasks_legacy_trigger.py` around lines
46 - 68, The file defines an unused test helper class
_RecordingSubscriptionQuery which is dead code; remove the entire
_RecordingSubscriptionQuery class definition (its __init__, filter, order_by,
limit, offset, all methods) from the test file so only the used helper
_RecordingKeysetSubscriptionQuery remains, and run tests to ensure no references
to _RecordingSubscriptionQuery exist before committing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/app/services/knowledge/indexing.py`:
- Around line 222-237: The helper function _prepare_indexing_runtime is missing
the required OpenTelemetry sync tracing decorator; add from
shared.telemetry.decorators import trace_sync and annotate
_prepare_indexing_runtime with `@trace_sync`(), and likewise apply `@trace_sync`()
to the other new sync helper(s) declared later in this module (the second helper
around the later helper block), ensuring both functions are decorated to create
span-level observability.

---

Nitpick comments:
In `@backend/app/services/background_chat_executor.py`:
- Around line 387-391: The except block that currently swallows exceptions when
awaiting dispatch_task should log the caught exception for observability without
changing behavior; update the except Exception: clause in
background_chat_executor.py (the block awaiting dispatch_task) to call the
existing logger (or add one) and emit a debug/exception-level log including the
exception details and context (e.g., mention dispatch_task and
accumulated_content or the related emitter) before returning accumulated_content
so the runtime behavior is unchanged but errors are visible in logs.

In `@backend/app/services/repository_job.py`:
- Around line 211-277: Docstrings for _update_github_repositories,
_update_gitlab_repositories, _update_gitee_repositories, and
_update_gitea_repositories incorrectly refer to the parameter as "User object";
update each method's docstring to reference RepositoryUserSnapshot (e.g., change
"User object" to "RepositoryUserSnapshot") and optionally add a brief
description matching the type, ensuring the Args section lists user:
RepositoryUserSnapshot for _update_github_repositories,
_update_gitlab_repositories, _update_gitee_repositories, and
_update_gitea_repositories.
- Line 75: The log call uses an unnecessary f-string with no placeholders;
replace the f-string in the logger.info call (the line logging "[repository_job]
Starting get all users task" inside repository_job / the get-all-users task)
with a plain string literal (remove the leading f) so it’s a normal string
instead of an f-string.

In `@backend/tests/tasks/test_subscription_tasks_legacy_trigger.py`:
- Around line 46-68: The file defines an unused test helper class
_RecordingSubscriptionQuery which is dead code; remove the entire
_RecordingSubscriptionQuery class definition (its __init__, filter, order_by,
limit, offset, all methods) from the test file so only the used helper
_RecordingKeysetSubscriptionQuery remains, and run tests to ensure no references
to _RecordingSubscriptionQuery exist before committing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d5faefbc-4404-48b2-a9e7-9d04055de1d9

📥 Commits

Reviewing files that changed from the base of the PR and between 9847969 and 93fb318.

📒 Files selected for processing (19)
  • backend/app/services/background_chat_executor.py
  • backend/app/services/jobs.py
  • backend/app/services/knowledge/indexing.py
  • backend/app/services/knowledge/summary_service.py
  • backend/app/services/rag/gateway.py
  • backend/app/services/rag/local_data_plane/indexing.py
  • backend/app/services/rag/local_gateway.py
  • backend/app/services/rag/remote_gateway.py
  • backend/app/services/repository_job.py
  • backend/app/tasks/subscription_tasks.py
  • backend/tests/services/knowledge/test_indexing.py
  • backend/tests/services/rag/test_local_data_plane_indexing.py
  • backend/tests/services/rag/test_local_gateway.py
  • backend/tests/services/rag/test_remote_gateway.py
  • backend/tests/services/test_background_chat_executor.py
  • backend/tests/services/test_repository_job.py
  • backend/tests/services/test_summary_service.py
  • backend/tests/tasks/test_knowledge_tasks.py
  • backend/tests/tasks/test_subscription_tasks_legacy_trigger.py

Comment on lines +222 to +237
def _prepare_indexing_runtime(
*,
db: Session,
knowledge_base_id: str,
attachment_id: int,
retriever_name: str,
retriever_namespace: str,
embedding_model_name: str,
embedding_model_namespace: str,
user_id: int,
user_name: str,
splitter_config: Optional[SplitterConfig],
splitter_config_dict: Optional[dict],
document_id: Optional[int],
kb_index_info: Optional[KnowledgeBaseIndexInfo],
) -> _IndexingPreparation:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add tracing decorators to the new sync helper boundaries.

Both new helpers are execution boundaries but currently miss @trace_sync(), which violates the repository tracing requirement and reduces span-level observability consistency.

Suggested patch
 from shared.telemetry import add_span_event
+from shared.telemetry.decorators import trace_sync
@@
+@trace_sync()
 def _prepare_indexing_runtime(
@@
+@trace_sync()
 def _run_indexing_gateway_calls(

As per coding guidelines: “Use OpenTelemetry tracing decorators from shared/telemetry/decorators.py: @trace_async() or @trace_sync() for functions, add_span_event() for events, set_span_attribute() for span attributes”.

Also applies to: 374-383

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/knowledge/indexing.py` around lines 222 - 237, The
helper function _prepare_indexing_runtime is missing the required OpenTelemetry
sync tracing decorator; add from shared.telemetry.decorators import trace_sync
and annotate _prepare_indexing_runtime with `@trace_sync`(), and likewise apply
`@trace_sync`() to the other new sync helper(s) declared later in this module (the
second helper around the later helper block), ensuring both functions are
decorated to create span-level observability.

Source: Coding guidelines

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (2)
backend/app/services/background_chat_executor.py (2)

79-86: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add the required docstring and tracing on the managed-session entrypoint.

with_managed_sessions() is a new public API with no docstring, and this new managed path still lacks the shared tracing decorators/span metadata the repo requires for Python services. As per coding guidelines, "Python code MUST include descriptive names and docstrings for public functions/classes" and "Use OpenTelemetry tracing decorators from shared/telemetry/decorators.py: @trace_async() or @trace_sync() for functions, add_span_event() for events, set_span_attribute() for span attributes."

Also applies to: 113-119

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/background_chat_executor.py` around lines 79 - 86, Add a
docstring to the public classmethod with_managed_sessions describing its purpose
and parameters, and add OpenTelemetry tracing: import trace_sync and
set_span_attribute from shared.telemetry.decorators and annotate the method with
`@trace_sync`(); inside the method set span attributes for "managed_sessions"=True
and "user_id" (use set_span_attribute) so the managed-session entrypoint emits
tracing metadata. Apply the same pattern (docstring + `@trace_sync`() + span
attributes) to the other managed-session factory method referenced around lines
113-119.

Source: Coding guidelines


67-76: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject mixed session ownership.

If an instance is created with both db and session_factory, execute() silently takes the managed-session branch and ignores self.db. That can move task writes outside the caller's transaction/session boundary with no signal to the caller.

Suggested guard
     def __init__(
         self,
         db: Session | None,
         user_id: int,
         *,
         session_factory: Callable[[], Session] | None = None,
     ):
+        if (db is None) == (session_factory is None):
+            raise ValueError("Provide exactly one of `db` or `session_factory`.")
         self.db = db
         self.user_id = user_id
         self.session_factory = session_factory

Also applies to: 113-119

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/background_chat_executor.py` around lines 67 - 76, The
constructor for BackgroundChatExecutor allows both db and session_factory to be
provided, but execute() silently prefers session_factory and ignores self.db,
which can leak writes outside the caller's transaction; change the __init__ (and
any other ctor/factory like the one referenced at lines 113-119) to validate
ownership: if both db and session_factory are supplied, raise a ValueError (or
similar) with a clear message refusing mixed session ownership; ensure execute()
continues to branch on session_factory vs db but now can assume only one is set.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@backend/app/services/background_chat_executor.py`:
- Around line 79-86: Add a docstring to the public classmethod
with_managed_sessions describing its purpose and parameters, and add
OpenTelemetry tracing: import trace_sync and set_span_attribute from
shared.telemetry.decorators and annotate the method with `@trace_sync`(); inside
the method set span attributes for "managed_sessions"=True and "user_id" (use
set_span_attribute) so the managed-session entrypoint emits tracing metadata.
Apply the same pattern (docstring + `@trace_sync`() + span attributes) to the
other managed-session factory method referenced around lines 113-119.
- Around line 67-76: The constructor for BackgroundChatExecutor allows both db
and session_factory to be provided, but execute() silently prefers
session_factory and ignores self.db, which can leak writes outside the caller's
transaction; change the __init__ (and any other ctor/factory like the one
referenced at lines 113-119) to validate ownership: if both db and
session_factory are supplied, raise a ValueError (or similar) with a clear
message refusing mixed session ownership; ensure execute() continues to branch
on session_factory vs db but now can assume only one is set.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ef18ccae-9457-4e1e-b7d9-f9feef03e5df

📥 Commits

Reviewing files that changed from the base of the PR and between 93fb318 and 8fc1494.

📒 Files selected for processing (4)
  • backend/app/services/background_chat_executor.py
  • backend/app/services/knowledge/summary_service.py
  • backend/tests/services/test_background_chat_executor.py
  • backend/tests/services/test_summary_service.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • backend/tests/services/test_background_chat_executor.py
  • backend/tests/services/test_summary_service.py
  • backend/app/services/knowledge/summary_service.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
frontend/e2e/tests/code-task.spec.ts (2)

58-65: 💤 Low value

Consider logging cleanup failures for debugging.

The afterAll hook silently swallows deletion errors (lines 60, 63), which hides resource cleanup issues. While best-effort cleanup is reasonable for e2e tests, logging failures would help identify leaked resources or permission issues during test debugging.

♻️ Optional improvement
  test.afterAll(async () => {
    if (codeTeam) {
-     await apiClient.deleteTeam(codeTeam.name).catch(() => {})
+     await apiClient.deleteTeam(codeTeam.name).catch((err) => {
+       console.warn(`Failed to delete team ${codeTeam.name}:`, err.message)
+     })
    }
    if (codeBot) {
-     await apiClient.deleteBot(codeBot.name).catch(() => {})
+     await apiClient.deleteBot(codeBot.name).catch((err) => {
+       console.warn(`Failed to delete bot ${codeBot.name}:`, err.message)
+     })
    }
  })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/code-task.spec.ts` around lines 58 - 65, The afterAll
cleanup silently swallows errors when deleting resources; modify the
test.afterAll block to catch and log failures instead of ignoring them by
capturing the error from apiClient.deleteTeam and apiClient.deleteBot
(referencing codeTeam, codeBot, and apiClient.deleteTeam/deleteBot) and calling
a logger or console.error with a descriptive message that includes the resource
name and the error so cleanup failures are visible during e2e debugging.

26-35: ⚡ Quick win

Strengthen API response typing for bot and team creation.

The inline type assertions on lines 34 and 54 (botResponse.data as { id?: number } | null) cast without validating the response structure. If the API contract changes or returns an unexpected shape, the cast succeeds but id extraction fails silently, producing unclear assertion failures. Consider defining a proper response interface or adding validation before extraction.

♻️ Suggested improvement

Define typed response interfaces:

interface BotCreateResponse {
  id: number
  name: string
  // ... other fields
}

interface TeamCreateResponse {
  id: number
  name: string
  // ... other fields
}

Then update the extraction logic:

  const botResponse = await apiClient.createBot({...})
  expect([200, 201]).toContain(botResponse.status)
- codeBot = { name: botName, id: (botResponse.data as { id?: number } | null)?.id }
+ const botData = botResponse.data as BotCreateResponse
+ codeBot = { name: botName, id: botData.id }
  expect(codeBot.id).toBeTruthy()

Apply the same pattern for team creation on lines 53-55.

Also applies to: 37-55

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/code-task.spec.ts` around lines 26 - 35, The code casts
API results directly (botResponse.data, teamResponse.data) which can hide shape
mismatches; define proper response interfaces (e.g., BotCreateResponse with id:
number, name: string and TeamCreateResponse with id: number, name: string),
update the creation calls to use those types, and add a small runtime
validation/type-guard that checks the presence and type of id on
botResponse.data and teamResponse.data before assigning to codeBot.id or team.id
so extraction fails with a clear error if the shape is wrong; locate and update
the references to botResponse, codeBot, teamResponse, and team in the test to
use the new interfaces and guard.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/e2e/tests/code-task.spec.ts`:
- Line 16: codePagePath currently interpolates codeTeam?.id which can produce
the literal "teamId=undefined"; update codePagePath to defensively handle
missing id by checking codeTeam?.id and either (a) return '/code' with no teamId
query when id is falsy, or (b) throw a clear Error/Assertion if an id is
required—choose one policy and implement consistently. Locate and change the
codePagePath function (and any callers in the test) to use this explicit check
so the URL cannot contain "teamId=undefined".

---

Nitpick comments:
In `@frontend/e2e/tests/code-task.spec.ts`:
- Around line 58-65: The afterAll cleanup silently swallows errors when deleting
resources; modify the test.afterAll block to catch and log failures instead of
ignoring them by capturing the error from apiClient.deleteTeam and
apiClient.deleteBot (referencing codeTeam, codeBot, and
apiClient.deleteTeam/deleteBot) and calling a logger or console.error with a
descriptive message that includes the resource name and the error so cleanup
failures are visible during e2e debugging.
- Around line 26-35: The code casts API results directly (botResponse.data,
teamResponse.data) which can hide shape mismatches; define proper response
interfaces (e.g., BotCreateResponse with id: number, name: string and
TeamCreateResponse with id: number, name: string), update the creation calls to
use those types, and add a small runtime validation/type-guard that checks the
presence and type of id on botResponse.data and teamResponse.data before
assigning to codeBot.id or team.id so extraction fails with a clear error if the
shape is wrong; locate and update the references to botResponse, codeBot,
teamResponse, and team in the test to use the new interfaces and guard.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c49edbae-09fa-410c-b7f2-73c178bc8b5c

📥 Commits

Reviewing files that changed from the base of the PR and between 8fc1494 and bfd9742.

📒 Files selected for processing (2)
  • backend/tests/integration/test_rag_remote_mode.py
  • frontend/e2e/tests/code-task.spec.ts

let codeBot: CreatedResource | null = null
let codeTeam: CreatedResource | null = null

const codePagePath = () => `/code?teamId=${codeTeam?.id}`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add defensive check in codePagePath() to prevent malformed URLs.

The function uses optional chaining on codeTeam?.id, which produces /code?teamId=undefined (a string literal, not absent parameter) if codeTeam is null or the id is undefined. While the beforeAll assertions on lines 35 and 55 should prevent this at runtime, the type system doesn't enforce it, and the URL would break silently if assertions are bypassed or removed during refactoring.

🛡️ Proposed fix
- const codePagePath = () => `/code?teamId=${codeTeam?.id}`
+ const codePagePath = () => {
+   if (!codeTeam?.id) {
+     throw new Error('codeTeam not initialized; ensure beforeAll completed')
+   }
+   return `/code?teamId=${codeTeam.id}`
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const codePagePath = () => `/code?teamId=${codeTeam?.id}`
const codePagePath = () => {
if (!codeTeam?.id) {
throw new Error('codeTeam not initialized; ensure beforeAll completed')
}
return `/code?teamId=${codeTeam.id}`
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/code-task.spec.ts` at line 16, codePagePath currently
interpolates codeTeam?.id which can produce the literal "teamId=undefined";
update codePagePath to defensively handle missing id by checking codeTeam?.id
and either (a) return '/code' with no teamId query when id is falsy, or (b)
throw a clear Error/Assertion if an id is required—choose one policy and
implement consistently. Locate and change the codePagePath function (and any
callers in the test) to use this explicit check so the URL cannot contain
"teamId=undefined".

@sunnights

Copy link
Copy Markdown
Collaborator

LGTM

@feifei325
feifei325 merged commit 6d36678 into wecode-ai:main Jun 10, 2026
22 checks passed
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.

2 participants