Skip to content

Conversation

wenzhengjiang
Copy link
Collaborator

@wenzhengjiang wenzhengjiang commented Sep 13, 2025

This PR introduces a User Memory feature to enhance the AI's contextual awareness and personalization. It includes two components: "Recent Conversations" for automatic, short-term context from chat history, and "Saved Memories" for long-term, user-directed information storage.

Key changes include the UserMemoryManager to handle memory operations, new settings for configuration, and seamless integration of memory context into the LLM system prompt.

See https://github.com/logancyang/obsidian-copilot/blob/3da77b4ddf247c2f0b659e1e5f912ebf4dd36d9a/src/memory/memory-design.md for implementation design details.

Copy link

@korbit-ai korbit-ai bot left a comment

Choose a reason for hiding this comment

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

Review by Korbit AI

Korbit automatically attempts to detect when you fix issues in new commits.
Category Issue Status
Performance Uncached system prompt with memory retrieval ▹ view
Readability Hardcoded memory configuration values ▹ view
Performance Repeated system prompt generation without caching ▹ view
Security Prompt injection vulnerability in LLM calls ▹ view
Design SRP violation in sendMessage method ▹ view ✅ Fix detected
Design SRP violation: memory-analysis logic lives in UI tab ▹ view
Design Hardcoded memory folder path may cause conflicts ▹ view
Functionality Memory field not restricted to user messages ▹ view ✅ Fix detected
Files scanned
File Path Reviewed
src/types/message.ts
src/settings/SettingsPage.tsx
src/settings/v2/components/CopilotPlusSettings.tsx
src/core/MessageRepository.ts
src/LLMProviders/chainManager.ts
src/core/ChatManager.ts
src/main.ts
src/settings/model.ts
src/components/Chat.tsx
src/LLMProviders/chainRunner/AutonomousAgentChainRunner.ts
src/constants.ts
src/LLMProviders/chainRunner/CopilotPlusChainRunner.ts
src/memory/UserMemoryManager.ts
src/LLMProviders/projectManager.ts

Explore our documentation to understand the languages and file types we support and the files we ignore.

Check out our docs on how you can make Korbit work best for you and your team.

Loving Korbit!? Share us on LinkedIn Reddit and X

@logancyang
Copy link
Owner

bugbot run

cursor[bot]

This comment was marked as outdated.

Copy link

@korbit-ai korbit-ai bot left a comment

Choose a reason for hiding this comment

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

Review by Korbit AI

Korbit automatically attempts to detect when you fix issues in new commits.
Category Issue Status
Documentation Missing validation criteria explanation ▹ view ✅ Fix detected
Logging Incorrect log level for error condition ▹ view ✅ Fix detected
Logging Incorrect log level for error condition ▹ view ✅ Fix detected
Readability Misleading async method naming ▹ view ✅ Fix detected
Documentation Missing purpose explanation in condensed message documentation ▹ view ✅ Fix detected
Performance Unnecessary function binding in filter ▹ view ✅ Fix detected
Functionality Inconsistent chain manager usage in memory operations ▹ view ✅ Fix detected
Files scanned
File Path Reviewed
src/settings/model.ts
src/memory/UserMemoryManager.ts
src/core/ChatManager.ts
src/LLMProviders/chainRunner/AutonomousAgentChainRunner.ts

Explore our documentation to understand the languages and file types we support and the files we ignore.

Check out our docs on how you can make Korbit work best for you and your team.

Loving Korbit!? Share us on LinkedIn Reddit and X

Comment on lines 25 to 28
/**
* Check if a message is a user message with valid condensed content
*/
private hasValidCondensedUserMessage(message: ChatMessage): boolean {

This comment was marked as resolved.

const conversationTitle = await this.extractConversationTitle(messages, chatModel);
const timestamp = new Date().toISOString().split(".")[0] + "Z"; // Remove milliseconds but keep Z for UTC
const userMessageTexts = messages
.filter(this.hasValidCondensedUserMessage.bind(this))

This comment was marked as resolved.

Comment on lines 383 to 384
const chainManager = this.plugin.projectManager.getCurrentChainManager();
const chatModel = chainManager.chatModelManager.getChatModel();

This comment was marked as resolved.

}
})
.catch((error) => {
logInfo(`[ChatManager] Failed to create condensed message for ${messageId}:`, error);

This comment was marked as resolved.

});
}
} catch (error) {
logInfo(`[ChatManager] Error setting up condensed message creation:`, error);

This comment was marked as resolved.

@wenzhengjiang
Copy link
Collaborator Author

bugbot run

cursor[bot]

This comment was marked as outdated.

Copy link

@korbit-ai korbit-ai bot left a comment

Choose a reason for hiding this comment

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

Review by Korbit AI

Korbit automatically attempts to detect when you fix issues in new commits.
Category Issue Status
Design Tight coupling to utility function ▹ view ✅ Fix detected
Files scanned
File Path Reviewed
src/memory/UserMemoryManager.ts

Explore our documentation to understand the languages and file types we support and the files we ignore.

Check out our docs on how you can make Korbit work best for you and your team.

Loving Korbit!? Share us on LinkedIn Reddit and X

const settings = getSettings();
const memoryFolderPath = settings.memoryFolderName;

await ensureFolderExists(memoryFolderPath);

This comment was marked as resolved.

@logancyang
Copy link
Owner

bugbot run

cursor[bot]

This comment was marked as outdated.

@logancyang
Copy link
Owner

I ran codex on this diff, can you check if these are real issues @wenzhengjiang

Key Findings and Potential Issues

  • Memory referencing ignores the enable/disable toggle when building system prompt

    • getSystemPromptWithMemory unconditionally reads memory content and adds <user_memory> if content exists, ignoring getSettings().enableMemory.
    • Impact: Disabling "Reference Recent Conversation" does not prevent memory content from being included in the prompt if the memory file exists.
    • Recommendation: Gate memory inclusion in getSystemPromptWithMemory by enableMemory.
  • Test mismatch with new folder creation utility

    • UserMemoryManager.ensureMemoryFolderExists now calls ensureFolderExists, which uses global.app.vault.getAbstractFileByPath and app.vault.adapter.mkdir. UserMemoryManager.test.ts still expects vault.createFolder calls and injects a local mockApp.
    • Impact: Tests may fail or not test intended paths due to mockApp.vault being stubbed while ensureFolderExists uses global.app, and __mocks__/obsidian.js lacks vault.adapter.mkdir.
    • Recommendation: Update tests to mock global.app.vault.adapter.mkdir or refactor ensureFolderExists to take an App reference. Update __mocks__/obsidian.js to include vault.adapter = { mkdir: jest.fn() }.
  • Asynchronous race: condensedMessage may be missing during memory update

    • Condensed message creation in ChatManager.createCondensedMessageAsync is asynchronous. Memory write via updateUserMemory(messages, chatModel) happens at "New Chat" time, with no guarantee all condensed messages are ready.
    • Impact: Saved conversation messages may lack condensed bullets, reducing memory value.
    • Recommendation: In UserMemoryManager.updateMemory, consider calling createCondensedMessage in-line for user messages lacking condensedMessage to backfill missing entries before finalizing the memory section.
  • Logger usage inconsistent in UI files

    • Chat.tsx, SettingsPage.tsx, and settings components still use console.error.
    • Guideline: "NEVER use console.log — use logging utilities."
    • Impact: Inconsistent and unstructured logging.
    • Recommendation: Replace remaining console.error instances with logError.
  • Global app usage vs. instance-based dependencies

    • ensureFolderExists depends on global.app, while tests and managers inject their own app instances.
    • Impact: Harder to test and reason about; potential breakage in non-Obsidian environments.
    • Recommendation: Prefer dependency injection of app or ensure tests set global app consistently.
  • getSystemPrompt path inconsistency in deprecated chain paths

    • chainManager.setChain still uses getSystemPrompt() (no memory) while chain runners call getSystemPromptWithMemory.
    • Impact: If residual paths call chains directly, memory won't be included consistently.
    • Recommendation: Remove deprecated chains if unused, or replace with getSystemPromptWithMemory(...).
  • Condensed message fallback may bloat memory

    • When the LLM returns a condensed message that isn't shorter, the function returns the original full message.
    • Impact: Potentially large bullets in memory, defeating the "condensed" intent.
    • Recommendation: Clamp fallback to a maximum length (e.g., 160–200 chars) or retry with a more forceful prompt.
  • Minor UX/formatting review notes

    • Conversation titles: "No summary" fallback might be better as "Untitled Conversation" or derived from the first user message.
    • Key conclusions threshold: A hard threshold on conversationText length (300 chars) is simplistic; consider checking the number of exchanges or a token estimate.

Files/Areas Reviewed

  • src/memory/UserMemoryManager.ts (+ tests)
  • src/settings/model.ts (+ getSystemPromptWithMemory)
  • src/constants.ts (DEFAULT_SETTINGS + new fields)
  • src/LLMProviders/chainRunner/{CopilotPlusChainRunner, AutonomousAgentChainRunner}.ts (system prompt integration)
  • src/core/{ChatManager, MessageRepository}.ts
  • src/components/Chat.tsx, src/settings/SettingsPage.tsx, settings/v2/CopilotPlusSettings.tsx
  • src/utils.ts (ensureFolderExists)

Recommendations Summary

  • Gate memory inclusion in system prompt by enableMemory (bug).
  • Fix tests and/or mocks to work with ensureFolderExists and global.app.vault.adapter.mkdir, or refactor to inject app.
  • Replace remaining console.error with logError.
  • Backfill missing condensed messages during memory writes, or otherwise ensure condensation completes before writing.
  • Clamp condensed message fallback length.
  • Remove or harmonize deprecated chain usages of getSystemPrompt.

@wenzhengjiang
Copy link
Collaborator Author

I ran codex on this diff, can you check if these are real issues @wenzhengjiang

Key Findings and Potential Issues

  • Memory referencing ignores the enable/disable toggle when building system prompt

    • getSystemPromptWithMemory unconditionally reads memory content and adds <user_memory> if content exists, ignoring getSettings().enableMemory.
    • Impact: Disabling "Reference Recent Conversation" does not prevent memory content from being included in the prompt if the memory file exists.
    • Recommendation: Gate memory inclusion in getSystemPromptWithMemory by enableMemory.
  • Test mismatch with new folder creation utility

    • UserMemoryManager.ensureMemoryFolderExists now calls ensureFolderExists, which uses global.app.vault.getAbstractFileByPath and app.vault.adapter.mkdir. UserMemoryManager.test.ts still expects vault.createFolder calls and injects a local mockApp.
    • Impact: Tests may fail or not test intended paths due to mockApp.vault being stubbed while ensureFolderExists uses global.app, and __mocks__/obsidian.js lacks vault.adapter.mkdir.
    • Recommendation: Update tests to mock global.app.vault.adapter.mkdir or refactor ensureFolderExists to take an App reference. Update __mocks__/obsidian.js to include vault.adapter = { mkdir: jest.fn() }.
  • Asynchronous race: condensedMessage may be missing during memory update

    • Condensed message creation in ChatManager.createCondensedMessageAsync is asynchronous. Memory write via updateUserMemory(messages, chatModel) happens at "New Chat" time, with no guarantee all condensed messages are ready.
    • Impact: Saved conversation messages may lack condensed bullets, reducing memory value.
    • Recommendation: In UserMemoryManager.updateMemory, consider calling createCondensedMessage in-line for user messages lacking condensedMessage to backfill missing entries before finalizing the memory section.
  • Logger usage inconsistent in UI files

    • Chat.tsx, SettingsPage.tsx, and settings components still use console.error.
    • Guideline: "NEVER use console.log — use logging utilities."
    • Impact: Inconsistent and unstructured logging.
    • Recommendation: Replace remaining console.error instances with logError.
  • Global app usage vs. instance-based dependencies

    • ensureFolderExists depends on global.app, while tests and managers inject their own app instances.
    • Impact: Harder to test and reason about; potential breakage in non-Obsidian environments.
    • Recommendation: Prefer dependency injection of app or ensure tests set global app consistently.
  • getSystemPrompt path inconsistency in deprecated chain paths

    • chainManager.setChain still uses getSystemPrompt() (no memory) while chain runners call getSystemPromptWithMemory.
    • Impact: If residual paths call chains directly, memory won't be included consistently.
    • Recommendation: Remove deprecated chains if unused, or replace with getSystemPromptWithMemory(...).
  • Condensed message fallback may bloat memory

    • When the LLM returns a condensed message that isn't shorter, the function returns the original full message.
    • Impact: Potentially large bullets in memory, defeating the "condensed" intent.
    • Recommendation: Clamp fallback to a maximum length (e.g., 160–200 chars) or retry with a more forceful prompt.
  • Minor UX/formatting review notes

    • Conversation titles: "No summary" fallback might be better as "Untitled Conversation" or derived from the first user message.
    • Key conclusions threshold: A hard threshold on conversationText length (300 chars) is simplistic; consider checking the number of exchanges or a token estimate.

Files/Areas Reviewed

  • src/memory/UserMemoryManager.ts (+ tests)
  • src/settings/model.ts (+ getSystemPromptWithMemory)
  • src/constants.ts (DEFAULT_SETTINGS + new fields)
  • src/LLMProviders/chainRunner/{CopilotPlusChainRunner, AutonomousAgentChainRunner}.ts (system prompt integration)
  • src/core/{ChatManager, MessageRepository}.ts
  • src/components/Chat.tsx, src/settings/SettingsPage.tsx, settings/v2/CopilotPlusSettings.tsx
  • src/utils.ts (ensureFolderExists)

Recommendations Summary

  • Gate memory inclusion in system prompt by enableMemory (bug).
  • Fix tests and/or mocks to work with ensureFolderExists and global.app.vault.adapter.mkdir, or refactor to inject app.
  • Replace remaining console.error with logError.
  • Backfill missing condensed messages during memory writes, or otherwise ensure condensation completes before writing.
  • Clamp condensed message fallback length.
  • Remove or harmonize deprecated chain usages of getSystemPrompt.

Most issues discovered by codex are valid 👍

@logancyang
Copy link
Owner

bugbot run

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