Skip to content

feat(memory): add agent memory health snapshot#1852

Merged
yyhhyyyyyy merged 4 commits into
devfrom
feat/agent-memory-health
Jun 30, 2026
Merged

feat(memory): add agent memory health snapshot#1852
yyhhyyyyyy merged 4 commits into
devfrom
feat/agent-memory-health

Conversation

@yyhhyyyyyy

@yyhhyyyyyy yyhhyyyyyy commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Adds a read-only Agent Memory Health snapshot and settings Health tab, with lazy loading, typed routes/client support, repository stats, i18n, and coverage for health metrics, refresh behavior, and native SQLite-gated table tests.

Summary by CodeRabbit

  • New Features

    • Added a new Memory Health tab with dashboard metrics, access breakdowns, top accessed items, pipeline/quality summaries, stale-embedding indicators, and recent maintenance failures (with empty/loading/error states).
    • Exposed memory health via the app’s IPC route and added a client method to retrieve health for DeepChat agents.
  • Bug Fixes

    • Persona anchor actions now emit the correct update event.
    • Health refresh logic is more reliable when switching tabs and after memory updates, avoiding stale UI.

@coderabbitai

coderabbitai Bot commented Jun 30, 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: 3171ab65-6cd2-47d0-bada-d40478b01c72

📥 Commits

Reviewing files that changed from the base of the PR and between b6de2aa and 98f5d1c.

📒 Files selected for processing (4)
  • .github/workflows/prcheck.yml
  • src/renderer/settings/components/MemoryHealthSection.vue
  • test/main/presenter/memoryPresenter.test.ts
  • test/renderer/components/MemoryHealthSection.test.ts
💤 Files with no reviewable changes (1)
  • .github/workflows/prcheck.yml
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/renderer/components/MemoryHealthSection.test.ts
  • src/renderer/settings/components/MemoryHealthSection.vue
  • test/main/presenter/memoryPresenter.test.ts

📝 Walkthrough

Walkthrough

Adds a memory health feature end-to-end: shared health contracts and keys, SQLite aggregation and read-model assembly, a new memory.getHealth route, renderer access, a Health tab with lazy refresh, locale strings, and tests. setPersonaAnchor now emits persona-anchor.

Changes

Memory Health Dashboard

Layer / File(s) Summary
Shared health contracts and keys
src/shared/types/agent-memory.ts, src/shared/contracts/events/memory.events.ts, src/shared/contracts/routes/memory.routes.ts, src/shared/contracts/routes.ts
Defines health key tuples and union types, adds persona-anchor to the update-reason schema, creates MemoryHealthSchema/MemoryHealthDto/createEmptyMemoryHealth, and registers memoryGetHealthRoute.
Presenter ports and update reason
src/main/presenter/memoryPresenter/types.ts, src/main/presenter/memoryPresenter/index.ts
Extends presenter repository ports with health-stat methods, re-exports AgentMemoryHealthStats, adds 'persona-anchor' to MemoryUpdateReason, and fixes setPersonaAnchor to emit persona-anchor.
SQLite health aggregation
src/main/presenter/sqlitePresenter/tables/agentMemory.ts, src/main/presenter/sqlitePresenter/tables/agentMemoryAudit.ts
Adds health stat aggregation helpers and query methods for memory rows and audit rows, plus stale-embedding counting and archive/top-accessed selection rules.
MemoryPresenter health read model
src/main/presenter/memoryPresenter/index.ts
Adds health computation constants, a top-accessed mapping helper, and getHealth(agentId) assembly for lifecycle, conflict, embedding, access, quality, and maintenance sections.
IPC route dispatch and renderer client
src/main/routes/index.ts, src/renderer/api/MemoryClient.ts
Wires memoryGetHealthRoute into main route dispatch with a DeepChat-only fallback and adds getHealth to the renderer memory client.
MemoryHealthSection component
src/renderer/settings/components/MemoryHealthSection.vue
Introduces the health dashboard component with loading, error, empty, and populated states, plus distribution bars, metric grids, top-accessed rows, and recent failure rows.
Health tab in MemoryManagerPanel
src/renderer/settings/components/MemoryManagerPanel.vue
Adds the Health tab trigger and pane, reactive health state, refresh logic, mutation-driven invalidation, and update watchers that keep the health view current.
Health locale strings
src/renderer/src/i18n/*/settings.json
Adds tabHealth, emptyHealth, and nested health metric, status, and kind strings across all locale files.
Tests
test/main/presenter/agentMemoryTable.test.ts, test/main/presenter/fakes/memoryFakes.ts, test/main/presenter/memoryPresenter.test.ts, test/main/routes/dispatcher.test.ts, test/main/routes/memoryDto.test.ts, test/renderer/api/clients.test.ts, test/renderer/components/MemoryHealthSection.test.ts, test/renderer/components/MemoryManagerDialog.test.ts
Covers SQLite health queries, fake repository behavior, presenter read-model assembly, route dispatch, DTO contracts, renderer client routing, the health section component, and the memory manager dialog health tab.

Sequence Diagram(s)

sequenceDiagram
  participant MemoryManagerPanel
  participant MemoryClient
  participant Bridge
  participant RoutesIndex
  participant MemoryPresenter
  participant AgentMemoryTable
  participant AgentMemoryAuditTable

  MemoryManagerPanel->>MemoryClient: getHealth(agentId)
  MemoryClient->>Bridge: invoke(memory.getHealth, { agentId })
  Bridge->>RoutesIndex: dispatchDeepchatRoute
  RoutesIndex->>MemoryPresenter: getHealth(agentId)
  MemoryPresenter->>AgentMemoryTable: getHealthStats(agentId)
  MemoryPresenter->>AgentMemoryTable: countStaleEmbeddings(agentId, dim, fingerprint)
  MemoryPresenter->>AgentMemoryTable: listTopAccessed(agentId, limit)
  MemoryPresenter->>AgentMemoryAuditTable: getHealthAuditStats(agentId, scanLimit, failuresLimit)
  MemoryPresenter-->>RoutesIndex: MemoryHealthDto
  RoutesIndex-->>Bridge: { health }
  Bridge-->>MemoryClient: result.health
  MemoryClient-->>MemoryManagerPanel: MemoryHealthDto
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ThinkInAIXYZ/deepchat#1770: Extends the same agent-memory update surface by adding persona-anchor to the memory update reason set.
  • ThinkInAIXYZ/deepchat#1794: This PR builds on the existing memory/audit tables and presenter surface by adding health aggregation and audit stats.
  • ThinkInAIXYZ/deepchat#1802: The new health view reuses the memory category model and bucketed memory data shape introduced there.

Poem

A rabbit peeks at rows in twos and threes,
And hops through health with graceful ease.
🐇 Top-accessed carrots, bright and neat,
Stale embeddings? Counted with tidy feet.
Now tabs go “health!” and audits sing,
بينما the memory garden starts to spring.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 title clearly matches the main change: adding an agent memory health snapshot in the memory subsystem.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/agent-memory-health

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.

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

🧹 Nitpick comments (1)
src/renderer/settings/components/MemoryHealthSection.vue (1)

21-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use stable keys instead of translated labels.

metric.label / row.label changes with locale and is not guaranteed unique across translations. Add a stable key/id from the metric name or DTO enum key, then bind :key to that.

Example pattern
-        :key="metric.label"
+        :key="metric.key"
     {
+      key: 'totalRows',
       label: t('settings.deepchatAgents.memoryManager.health.totalRows'),
       value: formatCount(health.totalRows)
     },

Also applies to: 37-38, 52-53, 67-68, 84-85, 98-99, 161-162

🤖 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 `@src/renderer/settings/components/MemoryHealthSection.vue` around lines 21 -
22, The loops in MemoryHealthSection.vue are using translated labels as Vue
keys, which can change by locale and may collide. Add a stable identifier such
as `id` or `key` derived from the metric name/DTO enum in the data model, then
update the `headlineMetrics` and row rendering loops to bind `:key` to that
stable field instead of `metric.label` or `row.label`. Apply the same change to
all repeated `v-for` blocks in this component that currently key off translated
text.
🤖 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 `@test/main/presenter/memoryPresenter.test.ts`:
- Around line 2188-2191: The test around setPersonaAnchor only asserts the first
persona-anchor emission because onMemoryChanged is cleared after the false call.
Update the memoryPresenter.test.ts case to assert that setPersonaAnchor('a',
v2!, false) also triggers onMemoryChanged with 'persona-anchor' before calling
mockClear, using the onMemoryChanged spy and the setPersonaAnchor method to
verify both emissions.

In `@test/renderer/components/MemoryHealthSection.test.ts`:
- Around line 122-133: The loaded-state test in MemoryHealthSection is using a
timezone-sensitive timestamp assertion, which makes the rendered month flaky
across runners. Update the test around mountSection/loadedHealth to avoid
relying on `createdAt: 3000`; either use a midday January timestamp that is
stable in all timezones or mock the date formatter so the `wrapper.text()` check
remains deterministic.

---

Nitpick comments:
In `@src/renderer/settings/components/MemoryHealthSection.vue`:
- Around line 21-22: The loops in MemoryHealthSection.vue are using translated
labels as Vue keys, which can change by locale and may collide. Add a stable
identifier such as `id` or `key` derived from the metric name/DTO enum in the
data model, then update the `headlineMetrics` and row rendering loops to bind
`:key` to that stable field instead of `metric.label` or `row.label`. Apply the
same change to all repeated `v-for` blocks in this component that currently key
off translated text.
🪄 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: 26b373ec-9e84-48c6-ae43-35955ee055e8

📥 Commits

Reviewing files that changed from the base of the PR and between 810fe69 and b6de2aa.

📒 Files selected for processing (41)
  • package.json
  • src/main/presenter/memoryPresenter/index.ts
  • src/main/presenter/memoryPresenter/types.ts
  • src/main/presenter/sqlitePresenter/tables/agentMemory.ts
  • src/main/presenter/sqlitePresenter/tables/agentMemoryAudit.ts
  • src/main/routes/index.ts
  • src/renderer/api/MemoryClient.ts
  • src/renderer/settings/components/MemoryHealthSection.vue
  • src/renderer/settings/components/MemoryManagerPanel.vue
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/de-DE/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/es-ES/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/renderer/src/i18n/id-ID/settings.json
  • src/renderer/src/i18n/it-IT/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/ms-MY/settings.json
  • src/renderer/src/i18n/pl-PL/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/tr-TR/settings.json
  • src/renderer/src/i18n/vi-VN/settings.json
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/shared/contracts/events/memory.events.ts
  • src/shared/contracts/routes.ts
  • src/shared/contracts/routes/memory.routes.ts
  • src/shared/types/agent-memory.ts
  • test/main/presenter/agentMemoryTable.test.ts
  • test/main/presenter/fakes/memoryFakes.ts
  • test/main/presenter/memoryPresenter.test.ts
  • test/main/routes/dispatcher.test.ts
  • test/main/routes/memoryDto.test.ts
  • test/renderer/api/clients.test.ts
  • test/renderer/components/MemoryHealthSection.test.ts
  • test/renderer/components/MemoryManagerDialog.test.ts

Comment thread test/main/presenter/memoryPresenter.test.ts
Comment thread test/renderer/components/MemoryHealthSection.test.ts
@yyhhyyyyyy yyhhyyyyyy merged commit 970129b into dev Jun 30, 2026
3 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.

1 participant