Prototype conversation history in sessionless Python workers - #392
JamesHWade wants to merge 7 commits into
Conversation
JamesHWade
left a comment
There was a problem hiding this comment.
Review of c523c94, compared with feat/history-exchange-tree.
The shared capture/restore implementation is a sound basis for this draft. Keep this PR stacked on #379: it is six commits ahead of its base and none behind. The base is 13 commits behind main; update that base separately before rebasing this feature.
Before exposing this as a supported workflow, address the public v2 enablement gap and reject writes from stale worker handles. I reproduced the overwrite with two independently loaded handles. Application-values-only saves also leave updated_at unchanged, so comparing that timestamp alone would miss this case. Any read-before-write guard still requires exclusive access; it is not an atomic concurrency guarantee.
Move the downstream Deputy issue link from package documentation into this PR description. Minor follow-ups are consistent JSON-validation errors, attachment persistence coverage, and direct coverage of selecting a pending exchange. Keep the app-side file-store cache limitation explicit. The system-prompt fixes and switch-test synchronization would also benefit #379 independently.
This remains a partial implementation of #391: Python worker continuation is implemented, while the R/ellmer worker use case still requires the R port. Keep the PR in draft and #391 open.
Verification for this review: inspected the current diff and base relationship; reproduced stale-handle overwrite, unchanged timestamps on values-only saves, and the different validation exceptions for NaN and datetime. The full test counts in the existing PR description were not rerun for this review.
Refs #391. Stacked on #379, targeting
feat/history-exchange-tree.A Python worker can restore the conversation branch selected in Shiny, continue it without a session, and save the result for the user's return. The worker uses the existing exchange record, store, turn adapter, and shared capture/restore implementation. Provider turns remain independent of display messages, so compaction preserves earlier display history and alternative branches.
This remains a private prototype at
shinychat._conversation.Conversation. It is not exported fromshinychat, advertised in the changelog, or included in published documentation. #379 must establish public v2 enablement before this becomes a supported API. The fixture README documents the draft setup, worker lifecycle, recovery, and corresponding R behavior contract.Input is saved before work begins; complete assistant messages are checkpointed as they arrive; context exit captures provider turns and terminal status. Workers reject incompatible or incomplete provider state and support explicit recovery from an earlier exchange. Failed output saves can be retried without duplicating messages.
Before each write, the handle compares canonical JSON for the stored record with the snapshot last loaded or successfully saved. A change or deletion raises
ConversationConflictError. This catches values-only changes even whenupdated_atis unchanged, preserves JSON boolean/number distinctions, and keeps the expected snapshot intact after a failed write. It detects already-stale handles; the comparison and write are not atomic. The caller still owns authorization, scheduling, and exclusive access for the entire load/work/save operation. Each returning Shiny session needs a fresh file store to avoid a stale process-local history list.Python is implemented; the R/ellmer worker use case still requires the planned R exchange-tree port and a supported R worker API. The downstream integration is tracked in Deputy #66. Application
valuesuses the existing conversation-level callbacks, with consistentValueErrorvalidation; exchange-local application-state hooks and multi-writer coordination remain separate work. #391 stays open.Validation at
c57099c:The extraction, chatlas system-prompt restoration fixes, and switch-test synchronization remain separate commits. Changes needed to reconcile #379 with main belong on that base first; this feature remains stacked on it. This PR remains a draft. GitHub CI status is reported by the checks below.