Skip to content

fix(core): persist full assistant parts and add e2e coverage#1131

Merged
omeraplak merged 4 commits into
mainfrom
fix/message-persistence-1130-e2e
Mar 4, 2026
Merged

fix(core): persist full assistant parts and add e2e coverage#1131
omeraplak merged 4 commits into
mainfrom
fix/message-persistence-1130-e2e

Conversation

@omeraplak

@omeraplak omeraplak commented Mar 4, 2026

Copy link
Copy Markdown
Member

PR Checklist

Please check if your PR fulfills the following requirements:

Bugs / Features

What is the current behavior?

When conversationPersistence.mode = "step" is used and the model invokes tools, stored assistant history can lose non-text parts. In affected flows, persisted messages can end up with only final text while reasoning and tool call/result context are missing, which breaks multi-turn continuity.

What is the new behavior?

  • Preserves full assistant parts during step checkpoint persistence/merge flows:
    • reasoning
    • tool-call
    • tool-result
    • text
  • Adds a dedicated packages/e2e workspace and true agent-level E2E coverage (mock LLM + real adapter persistence) for:
    • LibSQL
    • PostgreSQL
  • E2E assertions now verify DB records include expected tool part state and output fields turn-by-turn, not only text.
  • CI now runs generic E2E Tests jobs in PR, release, and prerelease workflows.

fixes #1130

Notes for reviewers

Validated locally with:

  • pnpm --filter @voltagent/e2e test

Also added core changeset:

  • .changeset/five-candles-care.md

Summary by cubic

Preserves full assistant parts (reasoning, tool calls/results, text) in step-mode by merging same-id assistant checkpoints and persisting tool state across flushes. Hardens conversation persistence by ensuring conversations exist and failing fast if they don’t; adds LibSQL/PostgreSQL E2E coverage and CI gating; fixes #1130.

  • Bug Fixes

    • Merge subsequent assistant checkpoints with the same id after an intermediate flush.
    • Persist tool part state and output fields turn-by-turn in stored messages.
    • Ensure conversation exists before saving steps/input; fail fast on errors and handle duplicate/unique violations across LibSQL/Postgres.
  • New Features

    • Added @voltagent/e2e workspace with agent-level persistence tests for LibSQL and PostgreSQL.
    • CI runs E2E jobs in PR, prerelease, and release; adds concurrency and skips E2E when no related changes are detected.

Written for commit e553579. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes

    • Preserves full assistant message parts (reasoning, tool calls/results, text) across checkpoint merges and flushes; ensures conversation steps are saved by auto-creating conversations when needed.
  • Tests

    • Added unit, integration, and end-to-end tests covering intermediate-flush merging and message/step persistence for LibSQL and PostgreSQL backends.
  • Chores

    • Added an end-to-end test package, test runner config, and CI jobs to run E2E tests in PR, prerelease, and release pipelines.

@changeset-bot

changeset-bot Bot commented Mar 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e553579

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@voltagent/core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ghost

This comment has been minimized.

@coderabbitai

coderabbitai Bot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Merges assistant messages with the same id to preserve reasoning, tool-call, tool-result, and text across intermediate flushes when conversationPersistence.mode = "step"; adds unit/integration and end-to-end tests (LibSQL & Postgres) and CI jobs for E2E runs; modifies ensureConversationExists to return a boolean and enforce precondition checks.

Changes

Cohort / File(s) Summary
Conversation Buffer
packages/core/src/agent/conversation-buffer.ts
Adds hasSameAssistantId merge path: incoming assistant messages with the same id are merged into the last assistant message to preserve parts.
Core Tests & Integration
packages/core/src/agent/conversation-buffer.spec.ts, packages/core/src/agent/memory-persistence.integration.spec.ts
Adds tests verifying merging across intermediate flushes and preservation of reasoning/tool-call/tool-result/text parts (integration test duplicated).
Memory Manager (logic & tests)
packages/core/src/memory/manager/memory-manager.ts, packages/core/src/memory/manager/memory-manager.spec.ts
Changes ensureConversationExists to return Promise<boolean>, introduces error classification, and enforces precondition checks; adds tests for auto-creation and failure skipping when ensureConversationExists returns false.
E2E Package & Tests
packages/e2e/package.json, packages/e2e/vitest.config.mts, packages/e2e/src/message-persistence.shared.ts, packages/e2e/src/message-persistence.libsql.e2e.spec.ts, packages/e2e/src/message-persistence.postgres.e2e.spec.ts
Adds @voltagent/e2e package, shared runFiveTurns/assertAssistantParts helpers, and LibSQL/Postgres E2E tests validating persisted assistant parts and step records.
CI: E2E Workflows
.github/workflows/prerelease.yml, .github/workflows/pull-request.yml, .github/workflows/release.yml
Adds e2e-tests job to PR/prerelease/release workflows, introduces change-detection gate in PR workflow, and updates job dependencies to include e2e-tests.
Changelog
.changeset/five-candles-care.md
Adds changelog entry documenting the fix and regression/E2E coverage.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Agent as Agent
    participant Buffer as ConversationBuffer
    participant Manager as MemoryManager
    participant DB as Database

    Agent->>Buffer: handleAssistantMessage(reasoning + tool-call)
    Buffer->>Buffer: append assistant message (parts: reasoning, tool-call)
    Agent->>Buffer: flush (checkpoint 1)
    Buffer->>Manager: persist pending message
    Manager->>DB: save message (parts: reasoning, tool-call)
    DB-->>Manager: ok
    Manager-->>Buffer: ack

    Agent->>Buffer: handleAssistantMessage(tool-result)
    Buffer->>Buffer: append tool-result part

    Agent->>Buffer: handleAssistantMessage(text, same assistant id)
    Buffer->>Buffer: detect same assistant id → merge parts into existing message

    Agent->>Buffer: flush (checkpoint 2)
    Buffer->>Manager: persist merged message
    Manager->>DB: save message (parts: reasoning, tool-call, tool-result, text)
    DB-->>Manager: ok
    Manager-->>Buffer: ack
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • lzj960515

Poem

🐇 Hop, I stitch each thought from start to end,
Reasoning, tool-call, result — nothing to mend.
Checkpoints pass, then parts reunite,
Five-turns kept cozy through day and night.
🥕✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: fixing core persistence of full assistant message parts and adding e2e test coverage.
Description check ✅ Passed The description includes all required sections and details: current behavior, new behavior, test coverage, changeset documentation, and issue linkage.
Linked Issues check ✅ Passed The PR addresses all critical requirements from issue #1130: preserves reasoning/tool-call/tool-result/text parts, adds E2E tests with real persistence adapters, persists tool state/output fields, and implements conversation existence checks.
Out of Scope Changes check ✅ Passed All changes are scoped to the stated objectives: core persistence fixes, memory manager hardening, E2E test infrastructure, and CI workflow integration for E2E tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/message-persistence-1130-e2e

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.

@cubic-dev-ai cubic-dev-ai 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.

4 issues found across 15 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/e2e/src/message-persistence.libsql.e2e.spec.ts">

<violation number="1" location="packages/e2e/src/message-persistence.libsql.e2e.spec.ts:39">
P2: Ensure the libsql client is closed even when assertions fail (e.g., wrap the query/assertion block in `try/finally` or close in `afterEach`).</violation>
</file>

<file name=".github/workflows/prerelease.yml">

<violation number="1" location=".github/workflows/prerelease.yml:58">
P3: The E2E workflow spins up a Postgres service that the tests never use (they start their own docker-compose DB on port 5433). This adds unnecessary runtime and resource overhead. Remove the service or update the tests/env to use it.</violation>
</file>

<file name=".github/workflows/pull-request.yml">

<violation number="1" location=".github/workflows/pull-request.yml:204">
P2: Change detection hard-codes `origin/main`, which can skip E2E tests for PRs whose base branch isn’t main. Use the PR base ref so the diff matches the actual target branch.</violation>
</file>

<file name=".github/workflows/release.yml">

<violation number="1" location=".github/workflows/release.yml:54">
P3: The new postgres service is redundant because the E2E test script spins up its own Postgres on port 5433 and the tests default to that port. This extra service is unused in CI and adds unnecessary startup time/resources.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread packages/e2e/src/message-persistence.libsql.e2e.spec.ts
Comment thread .github/workflows/pull-request.yml Outdated
Comment thread .github/workflows/prerelease.yml Outdated
Comment thread .github/workflows/release.yml Outdated
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Mar 4, 2026

Copy link
Copy Markdown

Deploying voltagent with  Cloudflare Pages  Cloudflare Pages

Latest commit: e553579
Status: ✅  Deploy successful!
Preview URL: https://f79faa92.voltagent.pages.dev
Branch Preview URL: https://fix-message-persistence-1130.voltagent.pages.dev

View logs

@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: 3

🧹 Nitpick comments (3)
.github/workflows/pull-request.yml (1)

176-213: E2E gate still pays PostgreSQL startup cost on every PR

Because service containers start before steps, Line 182-195 spins Postgres even when Line 201-212 decides to skip. Consider moving change detection to a lightweight precheck job and gating this job with if: at job level.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pull-request.yml around lines 176 - 213, The e2e-tests job
currently starts the postgres service unconditionally while the change detection
happens in the job steps (the step with id check_e2e), so the job still pays the
container startup cost; create a lightweight separate job (e.g., "e2e-precheck")
that runs the change detection logic (the same git diff check used in the step
with id check_e2e) and emits an output like e2e_changed, then gate the existing
e2e-tests job at the job level using an if: condition that references that
precheck output (e.g., if: needs.e2e-precheck.outputs.e2e_changed == 'true'), so
postgres and other services in e2e-tests are only started when changes actually
require E2E runs.
packages/e2e/package.json (1)

20-20: Separate local DB orchestration from CI test execution

Line 20 always starts Docker Compose inside the package script. Since CI jobs may already provide Postgres, split this into test:local (compose + vitest) and test:ci (vitest only) to avoid duplicate infra and config drift.

Possible script split
  "scripts": {
    "build": "echo \"No build step for `@voltagent/e2e`\"",
    "lint": "biome check .",
-   "test": "sh -c 'docker compose -f ../postgres/docker-compose.test.yaml up -d && vitest run --config vitest.config.mts; status=$?; docker compose -f ../postgres/docker-compose.test.yaml down -v; exit $status'"
+   "test": "pnpm run test:local",
+   "test:local": "sh -c 'docker compose -f ../postgres/docker-compose.test.yaml up -d && vitest run --config vitest.config.mts; status=$?; docker compose -f ../postgres/docker-compose.test.yaml down -v; exit $status'",
+   "test:ci": "vitest run --config vitest.config.mts"
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/e2e/package.json` at line 20, Split the combined "test" npm script
into two scripts: "test:local" which runs the Docker Compose orchestration and
then invokes the vitest runner (preserving the existing sequence and exit-status
propagation and the docker compose down -v cleanup using the same
../postgres/docker-compose.test.yaml and vitest run --config vitest.config.mts
command), and "test:ci" which runs only vitest run --config vitest.config.mts
(no Docker Compose). Update the package.json scripts section to replace the
single "test" entry with these two named scripts so CI can call "test:ci" while
local development uses "test:local".
packages/e2e/src/message-persistence.libsql.e2e.spec.ts (1)

39-73: Ensure client.close() always runs via finally.

If a query/assertion fails before the last line, the LibSQL client may remain open for the test process.

Suggested refactor
     const client = createClient({ url: dbUrl });
-
-    const conversationRows = await client.execute({
-      sql: `SELECT id, user_id, resource_id FROM ${tablePrefix}_conversations WHERE id = ?`,
-      args: [conversationId],
-    });
-    expect(conversationRows.rows).toHaveLength(1);
-    expect(conversationRows.rows[0]?.id).toBe(conversationId);
-    expect(conversationRows.rows[0]?.user_id).toBe(userId);
-    expect(conversationRows.rows[0]?.resource_id).toBe("persistence-e2e-agent");
-
-    const messageRows = await client.execute({
-      sql: `SELECT role, parts FROM ${tablePrefix}_messages WHERE conversation_id = ? AND user_id = ? ORDER BY created_at ASC`,
-      args: [conversationId, userId],
-    });
-    const assistantRows = messageRows.rows.filter((row) => row.role === "assistant");
-    expect(assistantRows).toHaveLength(5);
-
-    for (const [index, row] of assistantRows.entries()) {
-      const rawParts = row.parts;
-      if (typeof rawParts !== "string") {
-        throw new Error("Expected libsql parts to be JSON string.");
-      }
-      const parts = JSON.parse(rawParts) as UIMessage["parts"];
-      assertAssistantParts({ id: "libsql-row", role: "assistant", parts }, index + 1);
-    }
-
-    const stepCountRows = await client.execute({
-      sql: `SELECT COUNT(*) AS count FROM ${tablePrefix}_steps WHERE conversation_id = ? AND user_id = ?`,
-      args: [conversationId, userId],
-    });
-    expect(Number(stepCountRows.rows[0]?.count ?? 0)).toBeGreaterThan(0);
-
-    client.close();
+    try {
+      const conversationRows = await client.execute({
+        sql: `SELECT id, user_id, resource_id FROM ${tablePrefix}_conversations WHERE id = ?`,
+        args: [conversationId],
+      });
+      expect(conversationRows.rows).toHaveLength(1);
+      expect(conversationRows.rows[0]?.id).toBe(conversationId);
+      expect(conversationRows.rows[0]?.user_id).toBe(userId);
+      expect(conversationRows.rows[0]?.resource_id).toBe("persistence-e2e-agent");
+
+      const messageRows = await client.execute({
+        sql: `SELECT role, parts FROM ${tablePrefix}_messages WHERE conversation_id = ? AND user_id = ? ORDER BY created_at ASC`,
+        args: [conversationId, userId],
+      });
+      const assistantRows = messageRows.rows.filter((row) => row.role === "assistant");
+      expect(assistantRows).toHaveLength(5);
+
+      for (const [index, row] of assistantRows.entries()) {
+        const rawParts = row.parts;
+        if (typeof rawParts !== "string") {
+          throw new Error("Expected libsql parts to be JSON string.");
+        }
+        const parts = JSON.parse(rawParts) as UIMessage["parts"];
+        assertAssistantParts({ id: "libsql-row", role: "assistant", parts }, index + 1);
+      }
+
+      const stepCountRows = await client.execute({
+        sql: `SELECT COUNT(*) AS count FROM ${tablePrefix}_steps WHERE conversation_id = ? AND user_id = ?`,
+        args: [conversationId, userId],
+      });
+      expect(Number(stepCountRows.rows[0]?.count ?? 0)).toBeGreaterThan(0);
+    } finally {
+      client.close();
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/e2e/src/message-persistence.libsql.e2e.spec.ts` around lines 39 -
73, The test currently may leave the LibSQL client open if an assertion throws;
wrap the usage of client (created by createClient) and all client.execute/assert
logic in a try/finally block so that client.close() is always called in the
finally clause; ensure client is declared before the try and that the finally
calls client.close() even if earlier awaits or assertions fail.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/prerelease.yml:
- Around line 65-67: The workflow exposes Postgres on port 5432 but the e2e
tests expect port 5433, causing connectivity failures; update the workflow
service to align ports or export VOLTAGENT_E2E_POSTGRES_PORT so tests target the
same port — specifically change the service ports mapping to expose 5433:5432 or
set the environment variable VOLTAGENT_E2E_POSTGRES_PORT=5432/5433 (matching the
test default) in the job configuration so the e2e test runner and the workflow
Postgres service use the same port.

In `@packages/core/src/agent/memory-persistence.integration.spec.ts`:
- Line 292: The test assertion currently weakens types by using (part: any) when
mapping finalMessage.parts; change the callback to use the proper part type
(e.g., UIMessage["parts"][number] or let Type = typeof
finalMessage.parts[number] so the mapper reads (part:
UIMessage["parts"][number]) or infer the type via a typed const for finalMessage
before mapping) and update the mapping assertion to remove any while keeping the
same logic referencing finalMessage and its parts.

In `@packages/core/src/memory/manager/memory-manager.ts`:
- Around line 245-246: ensureConversationExists currently logs-and-swallows
failures so the subsequent call to
this.conversationMemory?.saveConversationSteps?.(steps) can run even when the
conversation wasn't created; change the flow to fail-fast by making
ensureConversationExists surface errors (throw or return a boolean) and then
guard the call to saveConversationSteps accordingly: either let
ensureConversationExists throw and remove its internal swallow, or check its
returned success value before calling conversationMemory.saveConversationSteps,
and if it failed, log and abort/throw to avoid orphaned steps. Reference
ensureConversationExists and saveConversationSteps/conversationMemory to locate
the fix.

---

Nitpick comments:
In @.github/workflows/pull-request.yml:
- Around line 176-213: The e2e-tests job currently starts the postgres service
unconditionally while the change detection happens in the job steps (the step
with id check_e2e), so the job still pays the container startup cost; create a
lightweight separate job (e.g., "e2e-precheck") that runs the change detection
logic (the same git diff check used in the step with id check_e2e) and emits an
output like e2e_changed, then gate the existing e2e-tests job at the job level
using an if: condition that references that precheck output (e.g., if:
needs.e2e-precheck.outputs.e2e_changed == 'true'), so postgres and other
services in e2e-tests are only started when changes actually require E2E runs.

In `@packages/e2e/package.json`:
- Line 20: Split the combined "test" npm script into two scripts: "test:local"
which runs the Docker Compose orchestration and then invokes the vitest runner
(preserving the existing sequence and exit-status propagation and the docker
compose down -v cleanup using the same ../postgres/docker-compose.test.yaml and
vitest run --config vitest.config.mts command), and "test:ci" which runs only
vitest run --config vitest.config.mts (no Docker Compose). Update the
package.json scripts section to replace the single "test" entry with these two
named scripts so CI can call "test:ci" while local development uses
"test:local".

In `@packages/e2e/src/message-persistence.libsql.e2e.spec.ts`:
- Around line 39-73: The test currently may leave the LibSQL client open if an
assertion throws; wrap the usage of client (created by createClient) and all
client.execute/assert logic in a try/finally block so that client.close() is
always called in the finally clause; ensure client is declared before the try
and that the finally calls client.close() even if earlier awaits or assertions
fail.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7cd43885-7ce4-4c3d-8f54-24cfc6f4b0ce

📥 Commits

Reviewing files that changed from the base of the PR and between 9751245 and 6b66a65.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • .changeset/five-candles-care.md
  • .github/workflows/prerelease.yml
  • .github/workflows/pull-request.yml
  • .github/workflows/release.yml
  • packages/core/src/agent/conversation-buffer.spec.ts
  • packages/core/src/agent/conversation-buffer.ts
  • packages/core/src/agent/memory-persistence.integration.spec.ts
  • packages/core/src/memory/manager/memory-manager.spec.ts
  • packages/core/src/memory/manager/memory-manager.ts
  • packages/e2e/package.json
  • packages/e2e/src/message-persistence.libsql.e2e.spec.ts
  • packages/e2e/src/message-persistence.postgres.e2e.spec.ts
  • packages/e2e/src/message-persistence.shared.ts
  • packages/e2e/vitest.config.mts

Comment thread .github/workflows/prerelease.yml Outdated
Comment on lines +65 to +67
ports:
- 5432:5432
options: >-

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 | 🟠 Major

Align Postgres port between workflow service and e2e test defaults.

The e2e Postgres spec uses 5433 by default (Line 16 in packages/e2e/src/message-persistence.postgres.e2e.spec.ts), but this job exposes 5432 and does not set VOLTAGENT_E2E_POSTGRES_PORT. That can make this CI job fail with an unreachable DB.

Suggested fix
       - name: Run E2E Tests
         run: pnpm --filter `@voltagent/e2e` test
+        env:
+          VOLTAGENT_E2E_POSTGRES_PORT: "5432"

Also applies to: 85-86

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prerelease.yml around lines 65 - 67, The workflow exposes
Postgres on port 5432 but the e2e tests expect port 5433, causing connectivity
failures; update the workflow service to align ports or export
VOLTAGENT_E2E_POSTGRES_PORT so tests target the same port — specifically change
the service ports mapping to expose 5433:5432 or set the environment variable
VOLTAGENT_E2E_POSTGRES_PORT=5432/5433 (matching the test default) in the job
configuration so the e2e test runner and the workflow Postgres service use the
same port.

Comment thread packages/core/src/agent/memory-persistence.integration.spec.ts Outdated
Comment thread packages/core/src/memory/manager/memory-manager.ts Outdated

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/memory/manager/memory-manager.spec.ts`:
- Around line 259-261: The structural cast for the spy drops type safety by
using "as any" on manager.ensureConversationExists; change the cast to the
actual method signature so the input parameter union includes UIMessage (e.g.
cast manager to { ensureConversationExists: (arg: Conversation | UIMessage) =>
Promise<boolean> } or the precise signature used in your code) and update the
vi.spyOn call to use that typed cast; also import UIMessage from "ai" if not
already imported so the typed refactor compiles.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 983de1c8-56bd-41a5-99a9-c4f48cbf806c

📥 Commits

Reviewing files that changed from the base of the PR and between 53f2dd2 and 11fb758.

📒 Files selected for processing (3)
  • packages/core/src/agent/memory-persistence.integration.spec.ts
  • packages/core/src/memory/manager/memory-manager.spec.ts
  • packages/core/src/memory/manager/memory-manager.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/agent/memory-persistence.integration.spec.ts

Comment thread packages/core/src/memory/manager/memory-manager.spec.ts

@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.

🧹 Nitpick comments (1)
packages/core/src/memory/manager/memory-manager.spec.ts (1)

297-299: Consider asserting ensureConversationExists call arguments as well.

You already assert call count; adding argument verification will better protect against wiring regressions.

♻️ Suggested assertion hardening
       expect(ensureConversationExistsSpy).toHaveBeenCalledTimes(1);
+      expect(ensureConversationExistsSpy).toHaveBeenCalledWith(
+        context,
+        "user-steps-fail",
+        "conv-steps-fail",
+        context.input,
+      );
       expect(saveConversationStepsSpy).not.toHaveBeenCalled();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/memory/manager/memory-manager.spec.ts` around lines 297 -
299, Add an assertion that the ensureConversationExists spy was called with the
expected arguments to guard against wiring regressions: in the test near the
ensureConversationExistsSpy and saveConversationStepsSpy assertions, assert
ensureConversationExistsSpy.toHaveBeenCalledWith(...) using the exact
conversation id/object and any context/options the test supplies (e.g., the
conversationId, userId or request payload used earlier in the test). Keep the
existing toHaveBeenCalledTimes(1) and ensure saveConversationStepsSpy remains
asserted as not called.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/core/src/memory/manager/memory-manager.spec.ts`:
- Around line 297-299: Add an assertion that the ensureConversationExists spy
was called with the expected arguments to guard against wiring regressions: in
the test near the ensureConversationExistsSpy and saveConversationStepsSpy
assertions, assert ensureConversationExistsSpy.toHaveBeenCalledWith(...) using
the exact conversation id/object and any context/options the test supplies
(e.g., the conversationId, userId or request payload used earlier in the test).
Keep the existing toHaveBeenCalledTimes(1) and ensure saveConversationStepsSpy
remains asserted as not called.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 04b089af-9cef-48eb-8c8e-64063d35ece6

📥 Commits

Reviewing files that changed from the base of the PR and between 11fb758 and e553579.

📒 Files selected for processing (1)
  • packages/core/src/memory/manager/memory-manager.spec.ts

@omeraplak
omeraplak merged commit 9a3ff6b into main Mar 4, 2026
24 checks passed
@omeraplak
omeraplak deleted the fix/message-persistence-1130-e2e branch March 4, 2026 16:56
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.

🔴 [CRITICAL BUG] After upgrade to latest version, reasoning and tool-call messages are completely LOST - only text remains

1 participant