Skip to content

🕐 feat: Configurable Retention Period for Temporary Chats #7917

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

ConstantTime
Copy link
Collaborator

@ConstantTime ConstantTime commented Jun 15, 2025

Summary

This PR implements configurable retention periods for temporary chats, replacing the hardcoded 30-day limit with flexible configuration options via environment variables or librechat.yaml. Users can now set retention periods from 1 day to 1 year based on their needs.

Closes #7673

Change Type

  • New feature (non-breaking change which adds functionality)

Changes Made

Core Implementation

  • New utility: api/server/utils/tempChatRetention.js
    • getTempChatRetentionDays(): Retrieves configured retention period with validation
    • createTempChatExpirationDate(): Creates expiration dates using configured period
    • Built-in validation (min: 1 day, max: 365 days) with fallback to defaults
  • Updated models: api/models/Message.js and api/models/Conversation.js now use configurable retention
  • Schema updates: Added temporaryChatRetentionDays to interface schema in packages/data-provider/src/config.ts
  • Configuration integration: Updated AppService.js to make config available to models

Configuration Options

  1. Environment Variable: TEMP_CHAT_RETENTION_DAYS=7
  2. LibreChat.yaml: interface.temporaryChatRetentionDays: 14
  3. Default: 30 days (maintains backward compatibility)

Validation & Safety

  • Minimum: 1 day (prevents immediate deletion)
  • Maximum: 365 days (prevents indefinite retention)
  • Priority: Config file > Environment variable > Default
  • Error handling: Invalid values fall back to defaults with warnings

Testing

Automated Testing

  • Test suite: api/server/utils/__tests__/tempChatRetention.test.js
  • Coverage: 12 test cases covering all scenarios
  • Edge cases: Invalid values, boundary conditions, precedence rules
  • Results: ✅ All tests passing

Manual Testing & Verification

Test 1: Default Behavior (30 days)

# Configuration: No custom settings
# Expected: 30-day retention

Database Verification:

// Conversation ID: 91e6a871-de82-4240-836e-7f83ea1ad4cc
Created: 2025-06-15T14:59:42.764Z
Expires: 2025-07-15T14:59:45.705Z
Retention: 30.00 days 

Results:

  • ✅ Conversation and messages both expire in exactly 30 days
  • ✅ Default behavior maintained for backward compatibility

Test 2: Custom 1-Day Retention

# Configuration: librechat.yaml
interface:
  temporaryChatRetentionDays: 1

Database Verification:

// Conversation ID: 4b5629af-fdc2-4a4c-83c2-4619f7e60ac7
Created: 2025-06-15T15:01:28.710Z
Expires: 2025-06-16T15:01:31.451Z
Retention: 1.00 days 

Results:

  • ✅ Configuration change immediately applied to new conversations
  • ✅ Precise 24-hour retention period
  • ✅ Both conversation and messages have consistent expiration dates
  • ✅ MongoDB TTL index will auto-delete expired records

Test 3: Configuration Priority

# Environment: TEMP_CHAT_RETENTION_DAYS=15
# Config file: temporaryChatRetentionDays: 1
# Expected: Config file wins (1 day)

Results:

  • ✅ Config file setting (1 day) took precedence over environment variable
  • ✅ Priority system working correctly

Database Schema Verification

// Conversation Document
{
  conversationId: "4b5629af-fdc2-4a4c-83c2-4619f7e60ac7",
  expiredAt: ISODate('2025-06-16T15:01:31.451Z'), // ✅ 1-day retention
  createdAt: ISODate('2025-06-15T15:01:28.710Z'),
  // ... other fields
}

// Message Documents
{
  messageId: "783e67d9-a6d4-403d-a91f-03eb6b7ad090",
  expiredAt: ISODate('2025-06-16T15:01:30.795Z'), // ✅ 1-day retention
  text: "Testing temp chat",
  // ... other fields
}

Documentation

  • Updated: librechat.example.yaml with configuration example and comments
  • Added: Comprehensive JSDoc comments in utility functions
  • Included: Validation ranges and error handling documentation

Backward Compatibility

  • Fully backward compatible: Existing installations continue working unchanged
  • Default behavior preserved: 30-day retention when no configuration is provided
  • No breaking changes: All existing temporary chats maintain their expiration dates

Performance Impact

  • Minimal overhead: Configuration loaded once at startup
  • Efficient validation: Simple numeric range checks
  • Database optimized: Uses existing MongoDB TTL indexes for cleanup

Security Considerations

  • Input validation: Prevents invalid retention periods
  • Bounds enforcement: Prevents both immediate deletion and indefinite retention
  • Error handling: Graceful fallback to safe defaults

@ConstantTime ConstantTime force-pushed the feat/configurable-temp-chat-retention branch from c145bde to 527a662 Compare June 16, 2025 11:16
@rubentalstra
Copy link
Collaborator

@ConstantTime pleae have a look at the CI failed test:

FAIL server/services/AppService.spec.js
  ● AppService › should correctly assign process.env and app.locals based on custom config

    expect(received).toEqual(expected) // deep equality

    - Expected  -  0
    + Received  + 11

    @@ -29,10 +29,21 @@
          },
        },
        "balance": Object {
          "enabled": true,
        },
    +   "config": Object {
    +     "balance": Object {
    +       "enabled": true,
    +     },
    +     "fileStrategy": "testStrategy",
    +     "registration": Object {
    +       "socialLogins": Array [
    +         "testLogin",
    +       ],
    +     },
    +   },
        "fileConfig": undefined,
        "fileStrategy": "testStrategy",
        "filteredTools": undefined,
        "imageOutputType": Any<String>,
        "includedTools": undefined,

      112 |     expect(process.env.CDN_PROVIDER).toEqual('testStrategy');
      113 |
    > 114 |     expect(app.locals).toEqual({
          |                        ^
      115 |       socialLogins: ['testLogin'],
      116 |       fileStrategy: 'testStrategy',
      117 |       interfaceConfig: expect.objectContaining({

      at Object.toEqual (server/services/AppService.spec.js:114:24)

@ConstantTime
Copy link
Collaborator Author

Addressed the above issue and build is passing now.

@@ -503,6 +503,7 @@ export const intefaceSchema = z
prompts: z.boolean().optional(),
agents: z.boolean().optional(),
temporaryChat: z.boolean().optional(),
temporaryChatRetentionDays: z.number().min(1).max(365).optional(),
Copy link
Owner

Choose a reason for hiding this comment

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

documentation update needed: availableTools

Copy link
Owner

Choose a reason for hiding this comment

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

also, nitpick: rename to temporaryChatRetention and make unit to hours for more granular customization

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Name update is done and documentation added here.

@alifa98
Copy link

alifa98 commented Jun 19, 2025

thank you @ConstantTime for adding this configuration.

I have a question and it is a little bit unrelated directly to this pull request, but I am curious if there is any mechanism in the code base to use this field of expiry date? or is it purely delegated to users to implement their own clean up system?

we can continue chatting in the following discussion topic if you think that we shouldn't discuss it here as it's an indirect problem related to this PR:

#7674

@ConstantTime ConstantTime added the ✨ enhancement New feature or request label Jun 19, 2025
@ConstantTime
Copy link
Collaborator Author

thank you @ConstantTime for adding this configuration.

I have a question and it is a little bit unrelated directly to this pull request, but I am curious if there is any mechanism in the code base to use this field of expiry date? or is it purely delegated to users to implement their own clean up system?

we can continue chatting in the following discussion topic if you think that we shouldn't discuss it here as it's an indirect problem related to this PR:

#7674

Hey @alifa98
No it's fine, we can discuss this here. Users don't have to worry about deletion mechanisms. Seems like this is being taken care by mongoDB itself. Example: https://github.com/danny-avila/LibreChat/blob/main/packages/data-schemas/src/schema/convo.ts#L46-L48

The expiredAt/expiresAt fields are actively used by MongoDB's built-in TTL feature to automatically delete expired documents without any manual intervention required. We just had to make that parameter configurable here.

@danny-avila
Copy link
Owner

thanks @ConstantTime !

@ConstantTime
Copy link
Collaborator Author

thanks @ConstantTime !

Hey @danny-avila
Sorry didn't get this. All good in this PR? Can we merge this? I have resolved the conflicts as well here.

* @param {TCustomConfig} [config] - The custom configuration object
* @returns {number} The retention period in hours
*/
function getTempChatRetentionHours(config) {
Copy link
Owner

Choose a reason for hiding this comment

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

Can you move this to packages/api ? All new backend-specific code should live, as much as possible.

Then, it gets imported from @librechat/api after its compiled i.e. npm run build:api

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done!

@danny-avila danny-avila changed the title feat: Add configurable retention period for temporary chats 🕐 feat: Configurable Retention Period for Temporary Chats Jun 25, 2025
@danny-avila danny-avila changed the base branch from main to dev June 25, 2025 19:39
@danny-avila
Copy link
Owner

Thanks for your work on this! Needed some additional changes that required moving more things over to packages/api:

Moved here including your original commits:
#8056

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Enhancement]: Configurable Retention Period for Temporary Chats
4 participants