Skip to content

🛂 feat: Filter Model-Bound Content by Source - #14425

Merged
danny-avila merged 50 commits into
devfrom
danny-avila/content-protection-seam
Aug 22, 2026
Merged

danny-avila merged 50 commits into
devfrom
danny-avila/content-protection-seam

Conversation

@danny-avila

@danny-avila danny-avila commented Jul 25, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

I added source-aware content filtering across model-bound data, including persisted conversation context, provider payloads, files, agent resources, and PII policy transitions.

  • Add optional source and field selection for message, file, tool, instruction, skill, memory, action metadata, and model-parameter content.
  • Preserve typed source provenance when projecting final provider messages, with a conservative fallback for the currently pinned @librechat/agents 3.6.9 contract.
  • Revalidate stored content at the model boundary so policies enabled after persistence are enforced without mutating Mongo records.
  • Freeze bounded, null-prototype snapshots before file, PII, and traversal phases; fail closed for proxies, accessors, sparse or oversized carriers, cycles, and unsafe raw-object shapes.
  • Share an 8 MiB aggregate materialization budget across submitted and stored message context; report an aggregate-only overflow as assembled_context, while retaining direct content_part inspection.
  • Scope provider-part snapshot overflows to affected message, file, tool, and instruction fields so unrelated filters do not reject safe calls.

The companion provenance contract is ready in agents PR #442. It should land and publish as @librechat/agents 3.6.10 before a separate dependency bump; this PR remains safe against 3.6.9 through its conservative fallback.

Change Type

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

Testing

  • Ran the focused protection suite: 9 suites / 459 tests passed.
  • Ran the persisted-history mock E2E in a clean lockfile install: 6 tests passed, including no Mongo side-effect assertions.
  • Built @librechat/api successfully.
  • Ran targeted ESLint, import-sorting, and whitespace checks successfully.
  • Replayed the three rebased route suites: 85 tests passed.

Test Configuration

  • CI=1 E2E_CHROMIUM_CHANNEL=chrome npx playwright test --config=e2e/playwright.config.mock.ts content-filters.persisted.spec.ts --reporter=line
  • npx jest src/middleware/modelBoundContent.spec.ts src/middleware/messageFilterPii.spec.ts src/protection/provenance.spec.ts src/protection/adapters/nested.spec.ts src/protection/adapters/submissions.spec.ts src/protection/adapters/messages.spec.ts src/protection/files.spec.ts src/protection/detectors/pattern.spec.ts src/protection/runtime.spec.ts --runInBand

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • I have commented in complex areas where intent is not obvious
  • I have made pertinent documentation changes
  • My changes do not introduce new warnings
  • I have written tests demonstrating that the feature works
  • Local unit tests pass with my changes

Copilot AI review requested due to automatic review settings July 25, 2026 00:14
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

Copilot AI 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.

Pull request overview

This PR refactors the existing optional messageFilter.pii behavior by introducing an internal “content protection” seam in packages/api, keeping the current default behavior and response contract while making inspection source-aware via structured content fragments.

Changes:

  • Introduces new internal protection types and a legacy-compatible PII inspector backed by a compiled-pattern detector with config-identity caching.
  • Adds adapters that extract/normalize inspectable text fragments from chat submissions and external message arrays (including quote normalization with source indices and merged quote+text inspection).
  • Updates the existing messageFilterPii middleware to use the new protection seam while preserving status codes and response payload shape.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/api/src/utils/quotes.ts Adds quote-entry normalization that preserves original source-array indices for downstream adapters while keeping existing string-quote normalization behavior.
packages/api/src/protection/types.ts Defines internal content fragment and finding metadata (source/provenance/path/format/treatment) for source-aware inspection.
packages/api/src/protection/legacy.ts Provides legacy-compatible inspector factory + finding→legacy match conversion to preserve existing middleware/public behavior.
packages/api/src/protection/legacy.spec.ts Adds tests for caching behavior, invalid-pattern warning behavior, first-match ordering, and avoiding reads after first finding.
packages/api/src/protection/detectors/pattern.ts Implements the legacy-pattern detector with starter/custom regex compilation and WeakMap caching by config identity.
packages/api/src/protection/adapters/messages.ts Adds a generator adapter to extract inspectable text fragments from external chat message arrays (string content and text-bearing parts).
packages/api/src/protection/adapters/messages.spec.ts Tests message adapter extraction rules and declared-role non-trust behavior.
packages/api/src/protection/adapters/chat.ts Adds adapter extracting chat submission fields (text/quotes/merged quote-text/answer/decisions) into ordered fragments matching legacy inspection order.
packages/api/src/protection/adapters/chat.spec.ts Tests chat adapter field ordering, quote index retention, merge behavior, and robustness around unstringifiable edited arguments.
packages/api/src/middleware/messageFilterPii.ts Switches the middleware’s inspection logic to the new protection seam while preserving the 400 response payload contract.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 46de7b1570

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila
danny-avila marked this pull request as ready for review July 25, 2026 01:53
@danny-avila danny-avila changed the title 🧩 feat: Introduce Optional Content Protection Seam 🛡️ feat: Add Source-Aware Content Filters Jul 25, 2026
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

1 similar comment
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59627b23f7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/share.ts Outdated
Comment thread api/server/routes/prompts.js Outdated
Comment thread packages/api/src/agents/skillFiles.ts Outdated
Comment thread packages/api/src/agents/skillFiles.ts Outdated

Copy link
Copy Markdown
Collaborator Author

@codex review

1 similar comment
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8358e1d654

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/api/src/protection/adapters/submissions.ts Outdated
Comment thread api/server/routes/share.js Outdated
Comment thread api/server/utils/import/importBatchBuilder.js Outdated
Comment thread api/server/routes/agents/tools.js
@danny-avila
danny-avila changed the base branch from main to dev July 25, 2026 18:21
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6b4304b2f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread api/server/controllers/assistants/chatV2.js
Comment thread packages/api/src/protection/files.ts
Comment thread api/server/controllers/assistants/contentFilter.js Outdated
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

1 similar comment
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 277e062ac2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread api/server/routes/messages.js Outdated
Comment thread packages/api/src/agents/handlers.ts Outdated
Comment thread api/server/services/createRunBody.js Outdated
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: bffc4a0bb5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 009a0bb493

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/api/src/protection/legacy.ts
Comment thread packages/api/src/files/code/preflight.ts Outdated
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

1 similar comment
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 32bd4c1ae7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Collaborator Author

@codex review

1 similar comment

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: d0b869cf18

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@danny-avila
danny-avila force-pushed the danny-avila/content-protection-seam branch from 170e125 to dacae85 Compare August 22, 2026 00:59
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current PR head dacae85. Confirm that this exact commit is the reviewed commit and ignore findings that apply only to earlier heads. The prior findings are addressed by fail-closed transcript scoping across both snapshot boundaries and non-blank canonical derived-text evidence.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dacae85f9f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/api/src/protection/files.ts
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review exact head 7c3cf0a

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7c3cf0a4b7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread api/server/routes/files/files.js Outdated
Comment thread api/server/routes/share.js Outdated
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review exact head ea9591b

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: ea9591bf7e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review exact head 1f62c15

@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review exact head 7758e71

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7758e71cc5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread api/server/routes/skills.js Outdated
Comment thread api/server/controllers/tools.js Outdated
Comment thread api/server/routes/memories.js Outdated
Comment thread api/server/routes/agents/actions.js Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d92331388

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +253 to +267
getModelBoundFileProjection() {
return projectModelBoundSourceFiles({
messageFilesBySourceMessageId: this.message_file_map,
sourceMessages: this.modelBoundStoredMessages,
steerFileIdsBySourceMessageId: this.modelBoundSteerFileIdsBySourceMessageId,
replayHistoricalFiles: this.options.resendFiles !== false,
historicalFiles: this.authorizedHistoricalFiles,
processedCurrentFiles: Array.isArray(this.options.attachments)
? this.options.attachments
: [],
canonicalCurrentFiles: Array.isArray(this.modelBoundCurrentFiles)
? this.modelBoundCurrentFiles
: [],
initiallyOverflowed: this.modelBoundHistoricalFileIdsOverflowed === true,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Move model-bound client orchestration into TypeScript

Move this model-bound projection and admission orchestration into packages/api and leave BaseClient as a thin caller. These new legacy-JavaScript methods decide which stored messages and canonical files contribute to the provider payload and whether traversal overflow fails closed, while the same file also implements deferred persistence around that admission; this security-sensitive backend logic therefore bypasses the repository-required TypeScript boundary. CLAUDE.mdL21-L24

Useful? React with 👍 / 👎.

Comment on lines +137 to +141
const prepareCodeOutputForInspection = async ({
req,
id,
name,
session_id,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Move code-output inspection preparation into TypeScript

Move this generated-artifact inspection implementation into packages/api and keep the legacy service as a thin transport adapter. prepareCodeOutputForInspection and its surrounding helpers choose the trusted Code API route, enforce aggregate download limits, sanitize names, sniff MIME types, decode raw content, and decide whether extracted-text evidence is complete; those decisions directly control whether file policy fails closed, but they currently bypass the repository-required TypeScript boundary. CLAUDE.mdL21-L24

Useful? React with 👍 / 👎.

const isStreaming = request.stream === true;
const summarizationConfig = appConfig?.summarization;

const uninspectableField = getBlockedOpaqueFileField(appConfig?.filters, request.input);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Ignore discarded Responses file payloads in fail-close checks

When files.pii.uninspectable is block for content, an Open Responses input_file containing only file_id or file_data is rejected here as opaque. This executor never forwards either value: convertInputToMessages in packages/api/src/agents/responses/service.ts converts an input_file into a text placeholder containing only its filename, so the selected file-content surface is not model-bound. Apply the opaque-file check to the actual converted/provider projection (while retaining the separate filename inspection) instead of rejecting discarded payload fields.

Useful? React with 👍 / 👎.

@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current PR head 9d92331. Confirm that this exact commit is the reviewed commit and ignore findings that apply only to earlier heads.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 9d92331388

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila danny-avila changed the title 🛡️ feat: Add Source-Aware Content Filters 🛂 feat: Filter Model-Bound Content by Source Aug 22, 2026
@danny-avila
danny-avila merged commit 67b7b44 into dev Aug 22, 2026
34 checks passed
@danny-avila
danny-avila deleted the danny-avila/content-protection-seam branch August 22, 2026 02:43
LogicalAbsurd pushed a commit to LogicalAbsurd/LibreChat that referenced this pull request Aug 27, 2026
* feat: introduce optional content protection seam

* feat: enforce source-aware content filters

* feat: complete source-aware content enforcement

* test: activate skill file-text fail-close fixtures

* fix: harden source-aware content filters

* fix: harden model-bound content filtering

* fix: preserve legacy filters and generated files

* fix: inspect shared scalar metadata

* test: align mocks with current dev dependencies

* feat: add persisted content filter safeguards

* feat: complete source-aware content filter enforcement

* fix: move resume content preflight into TypeScript

* fix: close content inspection edge cases

* fix: harden content protection boundaries

* fix: complete content protection safeguards

* test: align persisted memory filter coverage

* fix: reconcile content protection with current dev

* fix: reconcile content protection with latest dev

* fix: close content protection review gaps

* fix: enforce source-aware provider boundaries

* fix: preserve legacy PII preflight semantics

* test: stabilize stored branch preflight fixture

* fix: defer agent writes until protected model admission

* perf: harden source-aware model-bound filtering

* fix: canonicalize provider lineage before validation

* fix: satisfy model-bound callback type checks

* perf: Bound content protection filtering work

* fix: Bound submission array traversal

* fix: Stabilize bounded content snapshots

* fix: Scope model-bound traversal overflows

* fix: Preserve scoped content inspection

* fix: Accumulate aggregate traversal scopes

* fix: centralize content policy boundaries

* test: align deferred tool policy context

* test: align controller policy mocks

* style: normalize content protection imports

* fix: close content policy review gaps

* fix: narrow active skill policy config

* fix: address content protection review boundaries

* fix: retain exact provenance overflow sentinel

* fix: preserve literal and scoped provenance updates

* fix: narrow persisted edit provenance

* fix: isolate exact overflow attribution

* fix: centralize stored prompt protection

* fix: fail closed on incomplete transcript evidence

* fix: align canonical transcript routing

* refactor: centralize content policy preflights

* fix: isolate upload policy error typing

* style: sort policy preflight imports

* refactor: centralize content policy boundaries
danny-avila added a commit that referenced this pull request Sep 19, 2026
* 🗂️ fix: Keep a Running Attachment Chat in the Sidebar

Since #15694, a turn with model-bound attachments defers its user-message
write until the model admits the payload. That write was also what created
a new conversation's row, so for the whole first model call, which with a
long generated script or extended thinking can run for minutes, the
conversation did not exist. Any conversation-list refetch in that window
(starting another chat, deleting one, reloading) dropped the running chat
from the sidebar until its run finished, and GET /api/convos/:id answered
404 for it.

When attachments are the only reason to defer, the new conversation's row
is now written as the run starts, carrying the same fields the message
write would set but no message. The message itself stays deferred until
admission, and its write waits for a seed still in flight so the two
upserts never race. A content policy still holds back every write, the
row included, as #14425 intended.

The conversation half of saveMessageToDatabase moves into
saveConversationToDatabase so the seed and the message write share one
path.

* 🧱 refactor: Own Turn Conversation Writes in packages/api

The conversation half of a turn's writes (the row a message save
upserts, the retention context it stamps, and the new seed ahead of a
deferred first message) moves into `conversations/save.ts`, which takes
`getConvo`/`saveConvo` from the caller. BaseClient keeps only the
wiring: the retention lookup that must stay synchronous for Stop, the
message save, and the calls into the module.

The seed passes an empty `appendMessageIds`, which tells `saveConvo`
the row holds no messages yet, so it no longer reads the message list
before the upsert. It also resolves the conversation once and leaves it
on the request, so the deferred message save reuses it instead of
looking the conversation up again.

save.spec.ts drives the real data-schemas methods against an in-memory
MongoDB: the seed creates an empty row without reading messages, the
message save appends to it without a second lookup, an existing chat and
a subagent thread are left alone, a temporary chat keeps its retention,
and a failed lookup settles instead of rejecting.
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