Skip to content

Prototype conversation history in sessionless Python workers - #392

Closed
JamesHWade wants to merge 7 commits into
posit-dev:feat/history-exchange-treefrom
JamesHWade:codex/sessionless-history-workers
Closed

JamesHWade wants to merge 7 commits into
posit-dev:feat/history-exchange-treefrom
JamesHWade:codex/sessionless-history-workers

Conversation

@JamesHWade

@JamesHWade JamesHWade commented Sep 5, 2026

Copy link
Copy Markdown

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 from shinychat, 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 when updated_at is 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 values uses the existing conversation-level callbacks, with consistent ValueError validation; exchange-local application-state hooks and multi-writer coordination remain separate work. #391 stays open.

Validation at c57099c:

  • 1,027 Python tests pass, including stale saves across two handles, changed values and branches, deletion, changes during work, failed-write retries, JSON type distinctions, invalid values, attachments, and direct rejection of pending selections.
  • All 9 affected worker/v2-restore browser tests pass using installed Chrome. The worker test closes the Shiny session, invokes a separate Python process using real chatlas with a mocked HTTP boundary, then reopens the app and verifies display history, compacted provider turns, run metadata, and preserved alternative branches.
  • Ruff and Pyright pass. Wheel/sdist and API/site documentation builds pass; Quarto emits existing site warnings. Artifact checks confirm the implementation is packaged but absent from public exports and published docs.
  • Independent review of the remediation has no remaining actionable findings.

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.

@JamesHWade JamesHWade left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread pkg-py/src/shinychat/__init__.py Outdated
Comment thread pkg-py/src/shinychat/_conversation.py
Comment thread pkg-py/docs/history-workers.qmd Outdated
@JamesHWade JamesHWade changed the title Support conversation history in sessionless Python workers Prototype conversation history in sessionless Python workers Sep 5, 2026
@JamesHWade JamesHWade closed this Sep 5, 2026
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.

1 participant