Skip to content

chore: sync upstream v3.3.4; adopt its tool-output compaction under our bridge - #5

Merged
JumpLink merged 4 commits into
mainfrom
chore/sync-upstream-v3.3.4
Jul 29, 2026
Merged

JumpLink merged 4 commits into
mainfrom
chore/sync-upstream-v3.3.4

Conversation

@JumpLink

@JumpLink JumpLink commented Jul 29, 2026 •

Copy link
Copy Markdown
Collaborator

Important

Merge with a merge commit, not squash. Squashing an upstream sync collapses upstreams commits into one, so upstream/main stops being an ancestor of main and every future sync re-conflicts from the old merge base. (This happened on agents#4 and had to be repaired by force-pushing main back to the real merge.)

Upstream LibreChat-AI#342 ("Compact Structured Tool Output Before Provider Calls") reworked exactly the code our image handling extends, so this is a re-graft rather than a version bump. Merge together with faktenforum/LibreChat#5, which repins the SDK to ^3.3.4 as upstream now does.

What upstream now owns, and we stopped carrying

Ours before Now
toolContentToString collapsing tool-role content upstream's getBoundedSingleTextToolContent / serializeToolContentBounded in _convertMessagesToOpenAIParams — hardened against proxies and prototype tricks in ways ours was not
our own tool-result truncation in ToolNode upstream's compactToolContent + computer-call short-circuit, kept next to our artifact mirroring
our returning formatArtifactPayload upstream's projectArtifactPayload, which now does the tool-to-Human projection we used to do ourselves

What stays ours, now as options on upstream's function

The user message is verifiably still handled correctly

New src/messages/artifactProjectionVision.test.ts runs the projection and the strip in sequence and asserts, for a vision-capable and a non-vision model:

  • the role order never puts user straight after tool, and
  • the tool's own text output survives the image being dropped.

That last point is what makes the combination safe: upstream aggregates the tool content into the projected message before the artifact, so stripping the image leaves the real result text rather than an empty placeholder.

Also picks up upstream's Keenable scraper and keeps our custom reranker beside its new provider unions.

Verification

tsc clean, build clean, eslint 0 errors, import order clean, jest 3296 passed / 14 failed — the 4 failing suites are the known credential-bound ones (google, vertexai, anthropic) plus the langfuse routing test, all failing identically on pristine upstream.

danny-avila and others added 4 commits July 28, 2026 07:36
…t-AI#342)

* fix: compact structured tool output before provider calls

* fix: keep folded tool context provider-safe

* fix: enforce provider-safe context bounds

* fix: anchor provider payload checks to pruned usage

* fix: harden provider payload boundaries

* fix: recover from fallback payload guards
…#337)

Keenable already ships as a search provider; this adds it as a scraper so
a Keenable-only web-search stack (provider + scraper) needs no third-party
key. The scraper reads any URL as clean markdown via Keenable's fetch
endpoint, keyless by default:

- GET /v1/fetch/public (keyless) or /v1/fetch (X-API-Key, rate limit lifted)
- X-Keenable-Title attribution header; keyless public endpoint by default
- scrapeUrl/scrapeUrls (concurrent), extractContent, extractMetadata

Wired into the scraper factory under scraperProvider: 'keenable' and the
ScraperProvider union. The fetch endpoint is resolved independently of the
search endpoint (keenableApiUrl is search-only). 9 unit tests.
…our bridge

Upstream LibreChat-AI#342 ("Compact Structured Tool Output Before Provider Calls") reworked
exactly the code our image handling extends, so this is a re-graft rather than a
version bump.

What upstream now owns, and we stopped carrying:

- tool-role content stringification. `_convertMessagesToOpenAIParams` bounds and
  collapses tool content itself (`getBoundedSingleTextToolContent`,
  `serializeToolContentBounded`), so our `toolContentToString` helper is gone -
  upstream's version is hardened against proxies and prototype tricks in a way
  ours was not.
- `ToolNode` tool-result compaction (`compactToolContent` + the computer-call
  short-circuit), kept alongside our artifact mirroring into
  `additional_kwargs`.
- `formatAnthropicArtifactContent` -> `projectArtifactPayload`, which now does
  the tool-to-Human projection we used to do ourselves. Our own returning
  `formatArtifactPayload` is dropped in favour of it.

What stays ours, now expressed as options on upstream's function:

- `bridgeUserAfterTool` inserts an assistant turn between the tool results and
  the projected user message. Without it Mistral-backed endpoints (Scaleway)
  answer `400 Unexpected role 'user' after role 'tool'` - upstream converged on
  the same projection but still emits `user` directly after `tool`.
- the vision strip stays at the request choke point (`stripImagesFromMessages`).

The user message is verifiably still handled correctly: the new
`artifactProjectionVision.test.ts` runs the projection and the strip in sequence
and asserts, for a vision and a non-vision model, that the role order never puts
`user` straight after `tool` and that the tool's own text output survives the
image being dropped. That last part matters - upstream aggregates the tool
content into the projected message before the artifact, so stripping the image
leaves the result text rather than an empty placeholder.

Also picks up upstream's Keenable scraper and keeps our `custom` reranker beside
its new provider unions.

Verified: tsc clean, build clean, eslint 0 errors, import order clean, jest
3296 passed / 14 failed - the 4 failing suites are the known credential-bound
ones (google, vertexai, anthropic) plus the langfuse routing test, all failing
identically on pristine upstream.
@JumpLink
JumpLink merged commit 66716ff into main Jul 29, 2026
13 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.

3 participants