Skip to content

RDBC-1107 sync 7.2.5 -> 7.2.6 - #578

Merged
M4xymm merged 5 commits into
ravendb:v7.2from
M4xymm:RDBC-1107
Sep 9, 2026
Merged

RDBC-1107 sync 7.2.5 -> 7.2.6#578
M4xymm merged 5 commits into
ravendb:v7.2from
M4xymm:RDBC-1107

Conversation

@M4xymm

@M4xymm M4xymm commented Sep 9, 2026

Copy link
Copy Markdown
Member

Issue link

https://issues.hibernatingrhinos.com/issue/RDBC-1107

Description

Sync of the Node.js client with the C# client 7.2.5 -> 7.2.6 (CLIENT_VERSION 7.2.6, npm 7.2.8), plus the RavenDB-22293 change from the same C# release: session patches are emitted as RFC 6902 JsonPatch batch commands.

Synced from the C# 7.2.6 patch

  • AiOutputOptions: per-turn output schema override for AI conversations. run() / stream() accept { sampleObject | outputSchema | noSchema }, stream(callback) streams a plain text answer (empty streamPropertyPath), runWithSchema() / streamWithSchema() mirror the C# convenience overloads. OutputOptions is sent in the conversation request body. noSchema combined with a schema throws InvalidOperationException before contacting the server.
  • outputSchema (per turn and agent level) is forwarded to the model verbatim as response_format.json_schema, so it has to be the OpenAI-style { name, strict, schema } wrapper. Documented in JSDoc and README (a bare JSON schema makes the model answer in prose and the turn fails to parse).
  • No-args action tool handlers for handle() / receive() documented and tested.
  • storeChunkText on EmbeddingsGenerationConfiguration (serialized as StoreChunkText, part of isEqual).
  • AI exception names added to RavenErrorType (incl. QueryToolFailedException).
  • WhereToken.addAlias() no longer returns a copy with the alias applied twice; it updates the token in place and returns it, so VectorSearchToken keeps its shape. MoreLikeThisToken overrides addAlias() as a no-op (no field to prefix).
  • CdcSinkPostgresSettings doc comments.
  • Not ported: expression-tree (preferInterpretation) and Newtonsoft-only changes, no Node.js counterpart.

JsonPatch session patching (RavenDB-22293, C# SessionPatchBehavior)

  • New convention conventions.sessionPatchBehavior: "JsonPatch" | "JavaScript", default "JsonPatch" (same default as the C# client).
  • session.advanced.patch(), patchArray() and patchObject() emit a JsonPatch batch command when the path is a plain member/index chain and every value is null or a JSON primitive. One document gets one merged JsonPatch command per saveChanges(). Batch results are applied to tracked entities (change vector / metadata refresh) the same way as for JavaScript patches.
  • JavaScript fallback is kept for: object / Date values, increment(), addOrIncrement(), addOrPatch(), paths that are not plain member/index chains (e.g. tags[this.tags.length - 1]), removeAt() with a negative index, keys that are not valid JSON pointer segments, empty builders, and any operation queued after a JavaScript patch on the same document (order is preserved).
  • New public types: JsonPatchDocument (add / replace / remove / move / copy / test), JsonPatchCommandData (usable with session.advanced.defer()), SessionPatchBehavior. JavaScriptArray / JavaScriptMap record their operations; JavaScriptMap now uses bracket notation this.path["key"] in the JavaScript fallback so keys with spaces or dots work.
  • Ported tests: RavenDB_22293 (all client-portable cases), RavenDB_22750, MoreLikeThisTokenAliasTests, VectorSearchTokenAliasTests, RavenDB-24824 (offline: options plumbing and request body; the live OpenAI cases have no Node.js infrastructure). FirstClassPatchTest adjusted to the new default (deferred command counts, deferred JsonPatch command in the error message).

Notes for reviewers

  • The Node.js client never aliases where tokens on its own: addFromAliasToWhereTokens() has no internal callers (public on DocumentQuery only). The end-to-end alias tests call it explicitly, which is the only path that exercises the WhereToken.addAlias() fix.
  • JsonPatch is strict on the server: removeAt() past the end of the array or remove() of a missing key now makes saveChanges() throw where the JavaScript variants were silent no-ops. Covered by tests for both behaviors.

Type of change

  • Bug fix
  • Regression bug fix
  • Optimization
  • New feature
  • Sync with the C# client (version 7.2.5 -> 7.2.6)
  • Dependency / tooling / CI update

Target branch and backports

  • This PR targets the correct release branch (e.g. v7.2, v7.1, v7.0, v6.0)
  • The change needs to be ported to other release branches. Please list them.
  • No other release branch is affected

How risky is the change?

  • Low
  • Moderate
  • High
  • Not relevant

Backward compatibility

  • Non breaking change
  • Ensured. Please explain how has it been implemented?
  • Breaking change (public API, exported types, default behavior). Please describe the migration path.
  • Not relevant

session.advanced.patch() / patchArray() / patchObject() send JsonPatch commands by default instead of JavaScript scripts, and JsonPatch is strict (out-of-range removeAt(), remove() of a missing key and patch() on a non-existing array index throw instead of being no-ops). Migration path: set store.conventions.sessionPatchBehavior = "JavaScript" before store.initialize() to keep the previous behavior. WhereToken.addAlias() now returns the same token instance instead of a copy.

Server compatibility

  • Works with all RavenDB server versions covered by CI
  • Requires a minimum server version. Please specify which one and make sure the tests are gated accordingly.
  • Not relevant

JsonPatch batch commands are supported by every server version in the CI matrix. AiOutputOptions is only honored by a 7.2 server that includes RavenDB-24824 (7.2.6+); the AI tests stay gated to 7.1+ and the new ones run offline. Verified locally against 7.2.6 only; behavior of older servers receiving OutputOptions was not checked.

Affected runtimes

  • Node.js
  • Bun
  • Deno
  • Cloudflare Workers
  • Not runtime specific

Public API

  • New or changed public API. New types are exported from src/index.ts (npm run check-exports passes).
  • Version bump: package.json and CLIENT_VERSION in src/Http/RequestExecutor.ts (sync / release PRs only)
  • No public API changes

New exports: SessionPatchBehavior, JsonPatchCommandData, JsonPatchDocument, JavaScriptArray (AiOutputOptions via Documents/Operations/AI/index.ts). New methods: AiConversation.runWithSchema(), streamWithSchema(), stream(callback); run() / stream() accept AiOutputOptions. New convention sessionPatchBehavior, new field EmbeddingsGenerationConfiguration.storeChunkText. package.json 7.2.7 -> 7.2.8, CLIENT_VERSION 7.2.5 -> 7.2.6.

Documentation update

  • README.md has been updated
  • No documentation update is needed

Testing by Contributor

  • Tests have been added that prove the fix is effective or that the feature works

  • Existing tests verify the correct behavior

  • It has been verified by manual testing

  • npm run lint, npm run build, npm run check-exports and npm run check-imports pass locally

  • Tests have been run locally against a RavenDB server (RAVENDB_TEST_SERVER_PATH / RAVENDB_SERVER_VERSION)

  • Runtime-specific changes have been verified on the affected runtime (Bun / Deno / Cloudflare Workers)

  • Added: test/Ported/Issues/RavenDB_22293.ts, test/Ported/Issues/RavenDB_22750.ts, test/Ported/MoreLikeThis/MoreLikeThisTokenAliasTest.ts, test/Documents/Queries/VectorSearchTokenAliasTest.ts, test/Documents/Session/Tokens/WhereTokenAliasTest.ts, test/Documents/Commands/JsonPatchCommandDataTest.ts, test/Documents/Conventions/SessionPatchBehaviorTest.ts, test/Documents/Session/JavaScriptPatchBuildersTest.ts, test/Documents/Session/JsonPatchPathTest.ts, test/Ported/Documents/Operations/AiStreamingTest.ts; extended AiConversationTest.ts, EmbeddingsGenerationConfigurationTest.ts, FirstClassPatchTest.ts.

  • Run locally against RavenDB 7.2.6 (RAVENDB_SERVER_VERSION=7.2): the files above plus PatchTest, MoreLikeThisTest: 203 passing, 0 failing.

  • Manual testing: AiOutputOptions (sample object, explicit schema, noSchema, streaming) against a 7.2.6 server with Ollama (llama3.2).

  • npm run lint reports only pre-existing findings unrelated to this PR: gitignored test/cloudflare-nitro/.nitro/*.d.ts leftovers of a local Nitro build and the no-console warning in src/Auth/Certificate.ts. There is no build script; tshy (the prepare step) completes without errors. check-exports and check-imports pass.

Dependencies

  • New or updated runtime dependency. Please explain why it is needed and confirm it works on all affected runtimes.
  • Dev dependency only
  • No dependency changes

Is there any existing behavior change of other features due to this change?

  • Yes. Please list the affected features/subsystems and provide appropriate explanation

  • No

  • Session patching (session.advanced.patch() / patchArray() / patchObject()): JsonPatch commands by default, strict semantics, one merged command per document; increment() and friends unchanged. The "document modified by the session and also taking part in a deferred command" error now names the JsonPatch command.

  • Query aliasing: WhereToken.addAlias() mutates and returns the same token; MoreLikeThisToken is no longer aliased.

  • AI conversations: stream() accepts an empty property path when noSchema is set; the request body carries OutputOptions only when options are given.

@M4xymm M4xymm self-assigned this Sep 9, 2026
@M4xymm
M4xymm requested a review from kalczur September 9, 2026 10:55
@M4xymm
M4xymm marked this pull request as ready for review September 9, 2026 10:55
- Bump CLIENT_VERSION to 7.2.6 and package version to 7.2.8
- Add AiOutputOptions: per-turn output schema override (sampleObject /
  outputSchema / noSchema) on run() and stream(), stream(callback) for
  raw text answers, runWithSchema() / streamWithSchema() convenience
  methods; send OutputOptions in the conversation request body and allow
  an empty streamPropertyPath when streaming without a schema
- Document and test no-args action tool handlers for handle()/receive()
- Add storeChunkText to EmbeddingsGenerationConfiguration
- Fix WhereToken.addAlias() returning a copy with the alias applied twice;
  MoreLikeThisToken is no longer aliased
- Add AI exception names (incl. QueryToolFailedException) to RavenErrorType
- Update CdcSinkPostgresSettings doc comments

Not ported: expression-tree (preferInterpretation) and Newtonsoft-only
changes, which have no Node.js counterpart.
RDBC-1107 Address final review: pin removeAt(-1) fallback, document strictness, tidy exports

RDBC-1107 Document JsonPatch session patching

RDBC-1107 Emit JsonPatch from session.advanced.patchObject()

RDBC-1107 Assert the server error in the strict removeAt test

RDBC-1107 Emit JsonPatch from session.advanced.patchArray()

RDBC-1107 Align patch tests with the JsonPatch default

RDBC-1107 Emit JsonPatch from session.advanced.patch()

RDBC-1107 Fix JavaScriptArray/JavaScriptMap generic inference in DocumentSession

RDBC-1107 Apply JsonPatch batch results to tracked entities

RDBC-1107 Record operations on JavaScriptArray and JavaScriptMap, quote map keys

RDBC-1107 Add JSON pointer helper for session patch paths

RDBC-1107 Add sessionPatchBehavior convention
- RavenDB_22293: increment() under optimistic concurrency, increment()
  stays on JavaScript, tracked entity keeps saving after a JsonPatch
- RavenDB_22750: indexTimestamp/lastQueryTime are valid dates for an
  index that never ran (query, collection query, stream statistics)
- MoreLikeThisTokenAliasTests / VectorSearchTokenAliasTests: end-to-end
  from-alias on a JS-object projection keeps moreLikeThis() and
  vector.search() intact (alias applied via addFromAliasToWhereTokens)
@M4xymm
M4xymm merged commit 0520a63 into ravendb:v7.2 Sep 9, 2026
23 checks passed
M4xymm added a commit that referenced this pull request Sep 9, 2026
RDBC-1107 Follow-up to #578: order-by aliasing, empty output options, patchObject key docs
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