Repository navigation
chore: sync upstream v3.3.4; adopt its tool-output compaction under our bridge - #5
Merged
Merged
Conversation
…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.
This was referenced Jul 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
Merge with a merge commit, not squash. Squashing an upstream sync collapses upstreams commits into one, so
upstream/mainstops being an ancestor ofmainand every future sync re-conflicts from the old merge base. (This happened on agents#4 and had to be repaired by force-pushingmainback 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.4as upstream now does.What upstream now owns, and we stopped carrying
toolContentToStringcollapsing tool-role contentgetBoundedSingleTextToolContent/serializeToolContentBoundedin_convertMessagesToOpenAIParams— hardened against proxies and prototype tricks in ways ours was notToolNodecompactToolContent+ computer-call short-circuit, kept next to our artifact mirroringformatArtifactPayloadprojectArtifactPayload, which now does the tool-to-Human projection we used to do ourselvesWhat stays ours, now as options on upstream's function
bridgeUserAfterToolinserts an assistant turn between the tool results and the projected user message. Without it, Mistral-backed endpoints (Scaleway) answer400 Unexpected role 'user' after role 'tool'. Upstream converged on the same projection but still emitsuserdirectly aftertool— that is Tool image artifacts fail on strict OpenAI-compatible providers: 'Unexpected role user after role tool' LibreChat-AI/agents#344 / PR fix: bridge tool image artifacts with an assistant message for strict providers LibreChat-AI/agents#287.stripImagesFromMessages, PR feat(openai): optional vision gating to strip images for non-vision models LibreChat-AI/agents#257).The user message is verifiably still handled correctly
New
src/messages/artifactProjectionVision.test.tsruns the projection and the strip in sequence and asserts, for a vision-capable and a non-vision model:userstraight aftertool, andThat 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
customreranker 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.