Skip to content

Fix restored history, vectorization, swipe navigation, and Gallery agents - #4847

Merged
SpicyMarinara merged 7 commits into
stagingfrom
agent/assigned-issue-sweep-aug-10-round-2
Aug 10, 2026
Merged

Fix restored history, vectorization, swipe navigation, and Gallery agents#4847
SpicyMarinara merged 7 commits into
stagingfrom
agent/assigned-issue-sweep-aug-10-round-2

Conversation

@SpicyMarinara

@SpicyMarinara SpicyMarinara commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Why

Five assigned reports expose separate but user-visible dead ends: Conversation swipe navigation watches the wrong scroll surface; re-vectorization can race background memory work; Lorebook vectorization can execute before pending settings are saved and then report a misleading zero result; a restored profile can retain its pre-shard message backup while exposing no history; and custom image agents cannot be launched from the Gallery.

Scope

Changes

  • Resolve intuitive swipe gestures from the nearest marked Conversation or Roleplay transcript while preserving interactive-control guards.
  • Serialize background Memory Recall writes and full re-vectorization per chat, and expose an explicit Re-vectorize All action with confirmation and feedback.
  • Save pending Lorebook vector settings before vectorization and return actionable eligibility failures instead of silent zero-success responses.
  • Recover a manifest-expected history from a preserved pre-shard table only when no current shards exist; empty and partial histories remain untouched.
  • Let Gallery Illustrate choose between the active base Illustrator and active custom image-producing agents on desktop and mobile.
  • Add focused browser and server regressions for every repaired boundary.

Validation

  • Run pnpm check
  • Run pnpm localization:check
  • Run the message-sharding and Memory Recall re-vectorization regressions
  • Run focused mobile Conversation and Roleplay swipe coverage
  • Manually verify the Gallery selector in desktop and mobile layouts

Risk notes

The restored-history repair only recovers a preserved pre-shard backup when the current manifest expects rows and no shard data exists; it never merges ambiguous partial histories. Memory work is serialized per chat and releases its queue entry after completion. Gallery preserves its existing one-click behavior whenever no eligible custom image agent is active.

Summary by CodeRabbit

  • New Features
    • Added Gallery support for selecting active custom image-generation agents and retrying image generation with a chosen agent.
    • Added a confirmed “Re-vectorize All Memories” action with status reporting and error handling.
  • Bug Fixes
    • Improved mobile swipe navigation for conversation and roleplay alternatives.
    • Lorebook vectorization now saves pending changes first and reports excluded-content errors.
    • Improved memory re-vectorization reliability during concurrent updates.
    • Restored chat history when sharded backups are missing or incomplete.
  • Tests
    • Added regression coverage for Gallery agents, swipe navigation, lorebook settings, memory re-vectorization, and chat-history recovery.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@SpicyMarinara, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 6 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 93f13b80-371b-44c1-acb3-da58fadb614f

📥 Commits

Reviewing files that changed from the base of the PR and between 649a012 and 3262e33.

📒 Files selected for processing (2)
  • e2e/core-flows.e2e.ts
  • packages/client/src/components/lorebooks/LorebookEditor.tsx
📝 Walkthrough

Walkthrough

The pull request adds Gallery image-agent selection and fixes mobile swipe detection, Memory Recall re-vectorization concurrency, Lorebook vectorization persistence, and sharded chat-history recovery. It adds regression tests, localization strings, scripts, and changelog entries.

Changes

Chat interactions

Layer / File(s) Summary
Gallery image-agent selection
packages/client/src/components/chat/ChatGallery*.tsx, packages/client/src/components/chat/ChatCommonOverlays.tsx, packages/client/src/components/chat/ChatRoleplaySurface.tsx, packages/client/src/components/chat/ChatArea.tsx, packages/client/src/components/game/GameSurface.tsx, packages/client/src/hooks/use-capability-packages.ts, packages/client/src/localization/locales/en.json, e2e/core-flows.e2e.ts, CHANGELOG.md
The Gallery discovers eligible active image agents, displays a selector, and routes selected-agent generation with forced image generation.
Mobile transcript swipe detection
packages/client/src/components/chat/ChatArea.tsx, packages/client/src/components/chat/ConversationView.tsx, e2e/core-flows.e2e.ts
Swipe handling resolves the nearest marked chat scroll surface. Conversation and roleplay swipe navigation receive regression coverage.

Vectorization workflows

Layer / File(s) Summary
Serialized memory re-vectorization
packages/server/src/services/memory-recall.ts, packages/client/src/components/chat/ChatSettingsDrawer.tsx, scripts/regressions/memory-recall-revectorize.regression.ts, package.json, packages/client/src/localization/locales/en.json
Memory mutations now serialize per chat. The settings UI provides confirmed re-vectorization with localized success and error messages.
Lorebook save and vectorization flow
packages/client/src/components/lorebooks/LorebookEditor.tsx, packages/server/src/routes/lorebooks.routes.ts, e2e/core-flows.e2e.ts
Vectorization saves unsaved Lorebook changes first. The endpoint returns HTTP 409 for excluded lorebooks or entries.

Sharded history recovery

Layer / File(s) Summary
Pre-shard message recovery
packages/server/src/db/file-backed-store.ts, scripts/regressions/message-sharding.regression.ts, CHANGELOG.md
Migration restores missing message data from .pre-shard backups when valid manifest counts require rows. Empty, string, and fractional counts do not restore stale data.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ChatGalleryDrawer
  participant ChatGallery
  participant ChatRoleplaySurface
  User->>ChatGalleryDrawer: Open Gallery
  ChatGalleryDrawer->>ChatGallery: Pass eligible image agents
  User->>ChatGallery: Select an image agent
  ChatGallery->>ChatRoleplaySurface: Trigger selected agent
  ChatRoleplaySurface->>ChatRoleplaySurface: Force image generation
Loading

Possibly related PRs

Suggested labels: feature

Suggested reviewers: thetopham

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% 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
Title check ✅ Passed The title clearly summarizes the five primary fixes: restored history, vectorization, swipe navigation, and Gallery agent selection.
Description check ✅ Passed The description explains the problems, lists linked issues, summarizes changes, and provides validation steps, with only non-critical template sections omitted.
Linked Issues check ✅ Passed The changes address the linked requirements for swipe navigation [#4841], Memory Recall [#4843], Lorebook vectorization [#4844], history recovery [#4845], and Gallery agents [#4846].
Out of Scope Changes check ✅ Passed The implementation, changelog updates, package script change, and regression tests are directly related to the five linked issue objectives.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/assigned-issue-sweep-aug-10-round-2

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.

@SpicyMarinara
SpicyMarinara marked this pull request as ready for review August 10, 2026 06:35
@SpicyMarinara

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@packages/client/src/components/chat/ChatGallery.tsx`:
- Line 119: Add a ref for the illustrate-agent menu and a document-level
pointerdown handler tied to illustrateMenuOpen that closes the menu when the
event target is outside that menu. Update the menu rendering around the
illustrateMenuOpen state and its handlers, following the existing outside-click
pattern used by floating menus such as those in GameSurface.tsx, while
preserving clicks inside the menu.

In `@packages/client/src/components/chat/ChatGalleryDrawer.tsx`:
- Line 86: Update useCapabilityAgentRegistry to accept an enabled parameter like
useAgentConfigs, use that parameter to disable fetching when false, and pass
open from ChatGalleryDrawer so the registry request is gated consistently with
useInstalledCapabilityPackages and useAgentConfigs.

In `@packages/client/src/components/lorebooks/LorebookEditor.tsx`:
- Line 2878: Update the save/vectorization flow around handleSaveLorebook and
onBeforeVectorize so form mutations cannot occur while the pre-vectorization
save is awaited. Either disable relevant editor inputs for that await or capture
a form revision before onBeforeVectorize and abort vectorization when the
revision changes, ensuring stale settings are not persisted or processed.

In `@packages/server/src/db/file-backed-store.ts`:
- Around line 1245-1251: Validate expectedRowCount before the recovery condition
in the surrounding recovery logic: only allow recovery when the manifest value
for tables.messages is a positive safe integer, rejecting strings, fractions,
NaN, and other malformed values. Preserve the existing zero-shard and
absent-monolith checks, and add a regression covering string or fractional
tables.messages values to ensure stale .pre-shard data is not restored.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 55b2a449-2195-4a83-a301-3dd8ace4b31d

📥 Commits

Reviewing files that changed from the base of the PR and between 612d4d2 and 0b2de39.

📒 Files selected for processing (18)
  • CHANGELOG.md
  • e2e/core-flows.e2e.ts
  • package.json
  • packages/client/src/components/chat/ChatArea.tsx
  • packages/client/src/components/chat/ChatCommonOverlays.tsx
  • packages/client/src/components/chat/ChatGallery.tsx
  • packages/client/src/components/chat/ChatGalleryDrawer.tsx
  • packages/client/src/components/chat/ChatRoleplaySurface.tsx
  • packages/client/src/components/chat/ChatSettingsDrawer.tsx
  • packages/client/src/components/chat/ConversationView.tsx
  • packages/client/src/components/game/GameSurface.tsx
  • packages/client/src/components/lorebooks/LorebookEditor.tsx
  • packages/client/src/localization/locales/en.json
  • packages/server/src/db/file-backed-store.ts
  • packages/server/src/routes/lorebooks.routes.ts
  • packages/server/src/services/memory-recall.ts
  • scripts/regressions/memory-recall-revectorize.regression.ts
  • scripts/regressions/message-sharding.regression.ts

Comment thread packages/client/src/components/chat/ChatGallery.tsx
Comment thread packages/client/src/components/chat/ChatGalleryDrawer.tsx Outdated
Comment thread packages/client/src/components/lorebooks/LorebookEditor.tsx Outdated
Comment thread packages/server/src/db/file-backed-store.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
packages/client/src/components/lorebooks/LorebookEditor.tsx (1)

1496-1502: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not close the editor when handleSaveLorebook returns false.

At Lines 1855-1858, the save-and-close handler ignores this result. If the request fails or a newer edit occurs during the request, handleSaveLorebook returns false, but the handler still closes the editor and discards the unsaved form state.

Close the editor only after a successful save. Keep the warning visible when the save fails or becomes stale.

Proposed fix
             onClick={async () => {
-              await handleSaveLorebook();
+              const saved = await handleSaveLorebook();
+              if (!saved) return;
               setShowUnsavedWarning(false);
               closeDetail();
             }}
🤖 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 `@packages/client/src/components/lorebooks/LorebookEditor.tsx` around lines
1496 - 1502, Update the save-and-close handler around handleSaveLorebook so it
closes the editor only when that method returns true; preserve the current form
and warning state when saving fails or the result is stale.
🤖 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 `@packages/client/src/components/lorebooks/LorebookEditor.tsx`:
- Around line 1496-1502: Update the save-and-close handler around
handleSaveLorebook so it closes the editor only when that method returns true;
preserve the current form and warning state when saving fails or the result is
stale.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6694c09b-2bd8-44c3-8602-97531ac1a282

📥 Commits

Reviewing files that changed from the base of the PR and between 0b2de39 and 58d8d7b.

📒 Files selected for processing (7)
  • e2e/core-flows.e2e.ts
  • packages/client/src/components/chat/ChatGallery.tsx
  • packages/client/src/components/chat/ChatGalleryDrawer.tsx
  • packages/client/src/components/lorebooks/LorebookEditor.tsx
  • packages/client/src/hooks/use-capability-packages.ts
  • packages/server/src/db/file-backed-store.ts
  • scripts/regressions/message-sharding.regression.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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)
packages/client/src/components/lorebooks/LorebookEditor.tsx (2)

2885-2885: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Confirm Re-vectorize All before saving edits.

onBeforeVectorize() runs before the Re-vectorize All confirmation. If the user cancels the confirmation, the unsaved Lorebook changes have already been persisted. Move the pre-vectorization save after the confirmation block.

🤖 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 `@packages/client/src/components/lorebooks/LorebookEditor.tsx` at line 2885,
Reorder the save flow around the Lorebook editor’s `onBeforeVectorize()` call so
the Re-vectorize All confirmation completes before any pre-vectorization save
occurs. Ensure cancelling that confirmation exits without persisting unsaved
Lorebook changes, while preserving the existing save behavior after
confirmation.

1496-1502: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Prevent discard and close from racing with the in-flight save.

Line 1496 checks the form revision only after updateLorebook.mutateAsync completes. It does not cancel the request. While Line 1856 awaits, the discard action and the back button remain active. If the user discards or closes the editor, the pending request can still persist the old form snapshot.

Disable close and discard actions while saving, and serialize or cancel overlapping save requests.

Proposed guard
 const handleClose = useCallback(() => {
+  if (saving) return;
   if (lorebookDirty) {
     setShowUnsavedWarning(true);
   } else {
     closeDetail();
   }
-}, [lorebookDirty, closeDetail]);
+}, [lorebookDirty, saving, closeDetail]);

 <button
   onClick={() => {
     setShowUnsavedWarning(false);
     setLorebookDirty(false);
     closeDetail();
   }}
+  disabled={saving}
 >

Also applies to: 1856-1857

🤖 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 `@packages/client/src/components/lorebooks/LorebookEditor.tsx` around lines
1496 - 1502, Update the save flow around updateLorebook.mutateAsync and the
close/discard handlers near the save call to prevent races: disable back, close,
and discard actions whenever saving is true, and serialize or cancel overlapping
save requests so an in-flight save cannot persist a stale form snapshot after
the editor is closed or discarded. Preserve the existing formRevision check and
success/error behavior.
🤖 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 `@packages/client/src/components/lorebooks/LorebookEditor.tsx`:
- Line 2885: Reorder the save flow around the Lorebook editor’s
`onBeforeVectorize()` call so the Re-vectorize All confirmation completes before
any pre-vectorization save occurs. Ensure cancelling that confirmation exits
without persisting unsaved Lorebook changes, while preserving the existing save
behavior after confirmation.
- Around line 1496-1502: Update the save flow around updateLorebook.mutateAsync
and the close/discard handlers near the save call to prevent races: disable
back, close, and discard actions whenever saving is true, and serialize or
cancel overlapping save requests so an in-flight save cannot persist a stale
form snapshot after the editor is closed or discarded. Preserve the existing
formRevision check and success/error behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f827a12a-2c17-46fe-a53b-1795460e8ee6

📥 Commits

Reviewing files that changed from the base of the PR and between 58d8d7b and 2fbb766.

📒 Files selected for processing (2)
  • e2e/core-flows.e2e.ts
  • packages/client/src/components/lorebooks/LorebookEditor.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
e2e/core-flows.e2e.ts (1)

12545-12553: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert that cancellation does not start vectorization.

The test checks only saveRequestCount. An implementation can call /vectorize when the dialog opens, and this test still passes. Record vectorizeRequestCount before the click and assert that it is unchanged after cancellation.

Proposed test assertion
     const saveCountBeforeCancel = saveRequestCount;
+    const vectorizeCountBeforeCancel = vectorizeRequestCount;
     await revectorizeButton.click();
     const revectorizeDialog = page.getByRole("dialog").filter({ hasText: "Re-vectorize All Entries" });
     await expect(revectorizeDialog).toBeVisible();
     await revectorizeDialog.getByRole("button", { name: "Cancel", exact: true }).click();
     expect(saveRequestCount).toBe(saveCountBeforeCancel);
+    expect(vectorizeRequestCount).toBe(vectorizeCountBeforeCancel);
🤖 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 `@e2e/core-flows.e2e.ts` around lines 12545 - 12553, Update the cancellation
test around the lorebook dialog flow to capture the current
vectorizeRequestCount before clicking cancel, then assert it remains unchanged
afterward. Keep the existing saveRequestCount assertion and use the existing
vectorizeRequestCount tracking symbol.
🤖 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 `@packages/client/src/components/lorebooks/LorebookEditor.tsx`:
- Around line 2909-2911: Update handleVectorize to use an in-flight guard set
before showConfirmDialog, preventing concurrent vectorization confirmation flows
from starting. Keep the vectorization request blocked while the shared
onBeforeVectorize/handleSaveLorebook save is pending, and clear the guard in a
finally block so later attempts can proceed.

---

Outside diff comments:
In `@e2e/core-flows.e2e.ts`:
- Around line 12545-12553: Update the cancellation test around the lorebook
dialog flow to capture the current vectorizeRequestCount before clicking cancel,
then assert it remains unchanged afterward. Keep the existing saveRequestCount
assertion and use the existing vectorizeRequestCount tracking symbol.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a2e511a3-ddae-4433-9391-7eb2af0b766a

📥 Commits

Reviewing files that changed from the base of the PR and between 2fbb766 and 649a012.

📒 Files selected for processing (2)
  • e2e/core-flows.e2e.ts
  • packages/client/src/components/lorebooks/LorebookEditor.tsx

Comment thread packages/client/src/components/lorebooks/LorebookEditor.tsx Outdated
@SpicyMarinara

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@SpicyMarinara

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@SpicyMarinara
SpicyMarinara merged commit b14ecd0 into staging Aug 10, 2026
9 checks passed
@SpicyMarinara
SpicyMarinara deleted the agent/assigned-issue-sweep-aug-10-round-2 branch August 10, 2026 07:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant