Conversation
* fix(py,r): reject unsupported conversation-history schema versions (#313) * fix(py,r): reject unsupported conversation-history schema versions FileConversationStore/InMemoryConversationStore now validate schema_version on read (get/list) and write (put) against MIN_SCHEMA_VERSION/MAX_SCHEMA_VERSION, rejecting unsupported versions before decoding or before any filesystem mutation. HistoryController routes all store.get()/list() calls through internal helpers that validate records regardless of which ConversationStore implementation is in use, so custom stores can't bypass the check. Fixes #312 * test(py,r): cover schema-version rejection on read, write, and custom stores Adds tests for unsupported schema_version on get()/list(), rejecting writes into an empty store and over an existing unsupported record (asserting files are left byte-for-byte unchanged), InMemoryConversationStore input rejection, legacy missing-schema_version round-trip, and a custom ConversationStore whose output HistoryController rejects before it reaches client state. Also fixes two bugs surfaced by the new R tests in FileConversationStore: list()'s tryCatch handler re-signaled the unsupported-schema condition via stop(e), which was still caught by the sibling error handler in the same tryCatch call; and put()'s on-disk preflight used file.exists() without excluding directories, breaking the existing atomic-rename-failure test. Fixes #312 * docs(py,r): add changelog entries for schema-version rejection fix Fixes #312 * docs(py,r): reference PR in schema-version changelog entries * fix(py,r): harden schema version validation * docs(py,r): omit internal schema guard notes * Fix Python tool-result display serialization (#297) * fix(py): serialize dictionary tool result displays * fix(py): retain unknown tool display metadata * test(py): cover persisted dictionary tool displays * refactor(py): type chatlas turn serialization * fix(pkg-py): degrade gracefully on a malformed bookmarked message (#289) * fix(pkg-py): degrade gracefully on a malformed bookmarked message _restore_bookmark_message() raised on a malformed message dict (e.g. a bookmark written by an incompatible shinychat version), which aborts the caller's restore loop and silently drops every message after the bad one too -- Shiny's generic on_restore error handling only shows a banner, it doesn't resume the loop. Python has no turns-derived fallback to route into the way R's decode_ui_snapshot() does, so the proportionate fix here is per-message: warn and skip just the bad message, restoring everything else. * docs(pkg-py): changelog for the malformed bookmarked message skip * fix(pkg-py): don't leak message content into the malformed-bookmark warning ValidationError's default string embeds the offending input value, which for a chat segment is arbitrary (and possibly sensitive) message content. Use errors(include_input=False) and format loc/msg ourselves instead. * fix: resolve race between the chat greeting and history restore (#275) * fix(pkg-py): defer greeting to history's restore decision Resolving the app greeting used to race an independent client-side `{id}_greeting_requested` request against the server's async history restore: reloading into a restored conversation could flash the greeting before the restore replaced it, and a restored conversation's transcript had no way to suppress a stale/incoming greeting. Greeting resolution now defers to the same "is this conversation restored?" decision `HistoryController` already computes on init and on `new_chat()`, instead of a separate client-driven signal. Restoring a conversation (whether on initial load or via the history drawer) now explicitly clears any greeting, since a restored conversation is never a "new chat". * fix(pkg-r): defer greeting to history's restore decision Mirrors the pkg-py fix: resolving the app greeting used to race an independent client-side `{id}_greeting_requested` request against the server's async history restore, which could flash the greeting on a restored conversation, or leave a fresh conversation with no greeting at all if the session began by restoring one. Greeting resolution now defers to the same "is this conversation restored?" decision `HistoryController` already computes on init and on `new_chat()`. Restoring a conversation now explicitly clears any greeting, since a restored conversation is never a "new chat". * fix(pkg-py): add missing set_greeting support to history test fakes _ReplayFakeChat and _TrackingChat didn't implement set_greeting, which replay_ui() now calls to suppress the app greeting on restore. --------- Co-authored-by: Garrick Aden-Buie <garrick@adenbuie.com> * chore(pkg-py): prepare 0.6.1 release notes * chore(pkg-r): keep R package at v0.6.0 --------- Co-authored-by: Carson Sievert <cpsievert1@gmail.com>
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.
Summary
maininto the taggedpy-v0.6.1release branch sopy/v0.6.1remains in the ancestry when this work lands onmain.UNRELEASED.maineverywhere exceptpkg-py/CHANGELOG.md, preventing older release-branch implementations from replacing refined code onmain.Landing requirement
GitHub merge commits are disabled for this repository. After review, this PR must be landed manually without squash or rebase so
py/v0.6.1remains an ancestor ofmain.Verification
git diff --name-only origin/main..HEADreports onlypkg-py/CHANGELOG.md.py/v0.6.1andorigin/mainare ancestors of the reconciliation commit.0.6.2.dev23+gaa35a098.history_currentbrowser test completed successfully.