Skip to content

Conversation

@tomerqodo
Copy link

Benchmark PR from agentic-review-benchmarks#4

laipz8200 and others added 21 commits January 25, 2026 12:04
… factory to pass the ConversationVariableUpdater factory (the only non-VariablePool dependency), plus a unit test to verify the injection path.

- `api/core/workflow/nodes/variable_assigner/v2/node.py` adds a kw-only `conv_var_updater_factory` dependency (defaulting to `conversation_variable_updater_factory`) and stores it for use in `_run`.
- `api/core/workflow/nodes/node_factory.py` now injects the factory when creating VariableAssigner v2 nodes.
- `api/tests/unit_tests/core/workflow/nodes/variable_assigner/v2/test_variable_assigner_v2.py` adds a test asserting the factory is injected.

Tests not run.

Next steps (optional):
1) `make lint`
2) `make type-check`
3) `uv run --project api --dev dev/pytest/pytest_unit_tests.sh`
…ructor args.

- `api/core/workflow/nodes/node_factory.py` now directly instantiates `VariableAssignerNode` with the injected dependency, and uses a direct call for all other nodes.

No tests run.
Add a new command for GraphEngine to update a group of variables. This command takes a group of variable selectors and new values. When the engine receives the command, it will update the corresponding variable in the variable pool. If it does not exist, it will add it; if it does, it will overwrite it. Both behaviors should be treated the same and do not need to be distinguished.
…be-kanban 0941477f)

Create a new persistence layer for the Graph Engine. This layer receives a ConversationVariableUpdater upon initialization, which is used to persist the received ConversationVariables to the database. It can retrieve the currently processing ConversationId from the engine's variable pool. It captures the successful execution event of each node and determines whether the type of this node is VariableAssigner(v1 and v2). If so, it retrieves the variable name and value that need to be updated from the node's outputs. This layer is only used in the Advanced Chat. It should be placed outside of Core.Workflow package.
…rs/conversation_variable_persist_layer.py` to satisfy SIM118

- chore(lint): run `make lint` (passes; warnings about missing RECORD during venv package uninstall)
- chore(type-check): run `make type-check` (fails: 1275 errors for missing type stubs like `opentelemetry`, `click`, `sqlalchemy`, `flask`, `pydantic`, `pydantic_settings`)
…tType validation and casting

- test(graph-engine): update VariableUpdate usages to include value_type in command tests
… drop common_helpers usage

- refactor(variable-assigner-v2): inline updated variable payload and drop common_helpers usage

Tests not run.
…n and remove value type validation

- test(graph-engine): update UpdateVariablesCommand tests to pass concrete Variable instances
- fix(graph-engine): align VariableUpdate values with selector before adding to VariablePool

Tests not run.
…e handling for v1/v2 process_data

- refactor(app-layer): read updated variables from process_data in conversation variable persistence layer
- test(app-layer): adapt persistence layer tests to use common_helpers updated-variable payloads

Tests not run.
…fter venv changes)

- chore(type-check): run `make type-check` (fails: 1275 missing type stubs across dependencies)

Details:
- `make lint` fails with `ModuleNotFoundError: No module named 'dotenv_linter.cli'`.
- `make type-check` fails with missing stubs for `opentelemetry`, `click`, `sqlalchemy`, `flask`, `pydantic`, `pydantic_settings`, etc.
…ableUnion and remove value type validation"

This reverts commit 5ebc87a.
…h SegmentType validation and casting"

This reverts commit 3edd525.
…y out of core.workflow into `api/services/conversation_variable_updater.py`

- refactor(app): update advanced chat app runner and conversation service to import the new updater factory

Tests not run.
…-linter module missing)

- chore(type-check): run `make type-check` (fails: 1275 missing type stubs)

Details:
- `make lint` reports: `No matches for ignored import core.workflow.nodes.variable_assigner.common.impl -> extensions.ext_database` and ends with `ModuleNotFoundError: No module named 'dotenv_linter.cli'`.
- `make type-check` fails with missing type stubs for `opentelemetry`, `click`, `sqlalchemy`, `flask`, `pydantic`, `pydantic_settings`, etc.
@qodo-code-review
Copy link

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (4) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Session(db.engine) not context-managed 📘 Rule violation ⛯ Reliability
Description
• The new ConversationVariableUpdaterImpl.update() opens a SQLAlchemy session via
  Session(db.engine) without a context manager, and never closes it, risking connection leaks and
  inconsistent transaction cleanup.
• This violates the requirement that sessions be managed with context managers to ensure lifecycle
  correctness and reliability.
Code

api/services/conversation_variable_updater.py[R18-23]

+        session = Session(db.engine)
+        row = session.scalar(stmt)
+        if not row:
+            raise ConversationVariableNotFoundError("conversation variable not found in the database")
+        row.data = variable.model_dump_json()
+        session.commit()
Evidence
PR Compliance ID 11 requires SQLAlchemy sessions to be used with a context manager. The updated code
creates a session directly (session = Session(db.engine)) and performs work/commit without `with
... as session:` or explicit closing.

AGENTS.md
api/services/conversation_variable_updater.py[14-23]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`ConversationVariableUpdaterImpl.update()` creates a SQLAlchemy session without a context manager, which can leak connections and skip proper cleanup.

## Issue Context
Compliance requires context-managed sessions (e.g., `with Session(db.engine, expire_on_commit=False) as session:`) for safe lifecycle management.

## Fix Focus Areas
- api/services/conversation_variable_updater.py[14-23]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Updater raises non-domain exception 📘 Rule violation ✓ Correctness
Description
• The updater introduces ConversationVariableNotFoundError as a local Exception type rather than
  using a domain-specific exception from the standard services/errors or core/errors locations.
• This makes consistent controller-level translation and error semantics harder to enforce and
  violates the domain-exception policy.
Code

api/services/conversation_variable_updater.py[R9-22]

+class ConversationVariableNotFoundError(Exception):
+    pass


class ConversationVariableUpdaterImpl:
-    def update(self, conversation_id: str, variable: Variable):
+    def update(self, conversation_id: str, variable: Variable) -> None:
        stmt = select(ConversationVariable).where(
            ConversationVariable.id == variable.id, ConversationVariable.conversation_id == conversation_id
        )
-        with Session(db.engine) as session:
-            row = session.scalar(stmt)
-            if not row:
-                raise VariableOperatorNodeError("conversation variable not found in the database")
-            row.data = variable.model_dump_json()
-            session.commit()
-
-    def flush(self):
+        session = Session(db.engine)
+        row = session.scalar(stmt)
+        if not row:
+            raise ConversationVariableNotFoundError("conversation variable not found in the database")
+        row.data = variable.model_dump_json()
Evidence
PR Compliance ID 20 requires services to raise domain-specific exceptions from the project’s
designated error modules. The code defines a new generic exception inline and raises it from service
logic.

AGENTS.md
api/services/conversation_variable_updater.py[9-22]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A new inline generic exception (`ConversationVariableNotFoundError`) is introduced in a service module rather than using the repository’s domain-specific exception modules.

## Issue Context
Services should raise domain-specific exceptions from `services/errors` or `core/errors`, and controllers should translate them to HTTP responses.

## Fix Focus Areas
- api/services/conversation_variable_updater.py[9-22]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. __init__ missing -> None 📘 Rule violation ✓ Correctness
Description
• The newly added VariableAssignerNode.__init__ in v2 lacks an explicit return type annotation.
• This violates the requirement that all Python function definitions include full parameter and
  return type annotations using modern Python 3.12+ syntax.
Code

api/core/workflow/nodes/variable_assigner/v2/node.py[R56-62]

+    def __init__(
+        self,
+        id: str,
+        config: Mapping[str, Any],
+        graph_init_params: "GraphInitParams",
+        graph_runtime_state: "GraphRuntimeState",
+    ):
Evidence
PR Compliance ID 7 requires return type annotations on all functions. The added __init__
definition does not specify -> None.

AGENTS.md
api/core/workflow/nodes/variable_assigner/v2/node.py[56-62]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The newly added `__init__` method is missing a return type annotation.

## Issue Context
Type annotation compliance requires all function definitions to include return types.

## Fix Focus Areas
- api/core/workflow/nodes/variable_assigner/v2/node.py[56-62]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Tests lack return annotations 📘 Rule violation ✓ Correctness
Description
• Newly added pytest test functions (e.g.,
  test_persists_conversation_variables_from_assigner_output) do not include -> None return
  annotations.
• This violates the requirement that all Python function definitions include type annotations for
  parameters and return values.
Code

api/tests/unit_tests/core/app/layers/test_conversation_variable_persist_layer.py[63]

+def test_persists_conversation_variables_from_assigner_output():
Evidence
PR Compliance ID 7 requires explicit return type annotations on all function definitions. The added
test functions are defined without -> None.

AGENTS.md
api/tests/unit_tests/core/app/layers/test_conversation_variable_persist_layer.py[63-65]
api/tests/unit_tests/core/app/layers/test_conversation_variable_persist_layer.py[88-90]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New pytest test functions are missing return type annotations.

## Issue Context
Repository typing compliance requires all function definitions to have return type annotations.

## Fix Focus Areas
- api/tests/unit_tests/core/app/layers/test_conversation_variable_persist_layer.py[63-120]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



ⓘ The new review experience is currently in Beta. Learn more

Qodo Logo

Comment on lines +18 to +23
session = Session(db.engine)
row = session.scalar(stmt)
if not row:
raise ConversationVariableNotFoundError("conversation variable not found in the database")
row.data = variable.model_dump_json()
session.commit()

Choose a reason for hiding this comment

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

Action required

1. session(db.engine) not context-managed 📘 Rule violation ⛯ Reliability

• The new ConversationVariableUpdaterImpl.update() opens a SQLAlchemy session via
  Session(db.engine) without a context manager, and never closes it, risking connection leaks and
  inconsistent transaction cleanup.
• This violates the requirement that sessions be managed with context managers to ensure lifecycle
  correctness and reliability.
Agent prompt
## Issue description
`ConversationVariableUpdaterImpl.update()` creates a SQLAlchemy session without a context manager, which can leak connections and skip proper cleanup.

## Issue Context
Compliance requires context-managed sessions (e.g., `with Session(db.engine, expire_on_commit=False) as session:`) for safe lifecycle management.

## Fix Focus Areas
- api/services/conversation_variable_updater.py[14-23]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +9 to +22
class ConversationVariableNotFoundError(Exception):
pass


class ConversationVariableUpdaterImpl:
def update(self, conversation_id: str, variable: Variable):
def update(self, conversation_id: str, variable: Variable) -> None:
stmt = select(ConversationVariable).where(
ConversationVariable.id == variable.id, ConversationVariable.conversation_id == conversation_id
)
with Session(db.engine) as session:
row = session.scalar(stmt)
if not row:
raise VariableOperatorNodeError("conversation variable not found in the database")
row.data = variable.model_dump_json()
session.commit()

def flush(self):
session = Session(db.engine)
row = session.scalar(stmt)
if not row:
raise ConversationVariableNotFoundError("conversation variable not found in the database")
row.data = variable.model_dump_json()

Choose a reason for hiding this comment

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

Action required

2. Updater raises non-domain exception 📘 Rule violation ✓ Correctness

• The updater introduces ConversationVariableNotFoundError as a local Exception type rather than
  using a domain-specific exception from the standard services/errors or core/errors locations.
• This makes consistent controller-level translation and error semantics harder to enforce and
  violates the domain-exception policy.
Agent prompt
## Issue description
A new inline generic exception (`ConversationVariableNotFoundError`) is introduced in a service module rather than using the repository’s domain-specific exception modules.

## Issue Context
Services should raise domain-specific exceptions from `services/errors` or `core/errors`, and controllers should translate them to HTTP responses.

## Fix Focus Areas
- api/services/conversation_variable_updater.py[9-22]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +56 to +62
def __init__(
self,
id: str,
config: Mapping[str, Any],
graph_init_params: "GraphInitParams",
graph_runtime_state: "GraphRuntimeState",
):

Choose a reason for hiding this comment

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

Action required

3. init missing -> none 📘 Rule violation ✓ Correctness

• The newly added VariableAssignerNode.__init__ in v2 lacks an explicit return type annotation.
• This violates the requirement that all Python function definitions include full parameter and
  return type annotations using modern Python 3.12+ syntax.
Agent prompt
## Issue description
The newly added `__init__` method is missing a return type annotation.

## Issue Context
Type annotation compliance requires all function definitions to include return types.

## Fix Focus Areas
- api/core/workflow/nodes/variable_assigner/v2/node.py[56-62]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

)


def test_persists_conversation_variables_from_assigner_output():

Choose a reason for hiding this comment

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

Action required

4. Tests lack return annotations 📘 Rule violation ✓ Correctness

• Newly added pytest test functions (e.g.,
  test_persists_conversation_variables_from_assigner_output) do not include -> None return
  annotations.
• This violates the requirement that all Python function definitions include type annotations for
  parameters and return values.
Agent prompt
## Issue description
New pytest test functions are missing return type annotations.

## Issue Context
Repository typing compliance requires all function definitions to have return type annotations.

## Fix Focus Areas
- api/tests/unit_tests/core/app/layers/test_conversation_variable_persist_layer.py[63-120]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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.

3 participants