Skip to content

πŸ¦‹ New version release - #552

Merged
brentrager merged 1 commit into
mainfrom
changeset-release/main
Aug 26, 2026
Merged

brentrager merged 1 commit into
mainfrom
changeset-release/main

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@smooai/smooth-operator@1.58.5

Patch Changes

  • b3ad578: fix(server): a pending write-confirmation survives the pod that parked it (th-db0816)

    The write-confirmation park was a channel into a turn running on ONE pod. A
    visitor whose refresh reconnected them to a different replica β€” or whose pod
    rolled mid-park β€” got NO_PENDING_CONFIRMATION for an approval the agent had
    just asked them to give, and the approved write was silently lost. With 2-6
    replicas and no session affinity, that is the expected outcome for any
    reconnect, not a rare race.

    The confirmation bridge now mirrors every park into the session's durable
    metadata.pendingConfirmation (tool name + arguments + prompt + requestedAt)
    through the same SessionUpdate.metadata write-through the session registry
    already uses: storage is the truth, the in-process channel map is the same-pod
    fast path. confirm_tool_action that finds no live sender reads the record
    FRESH from storage and resolves it there:

    • Approved β†’ the record is retired first, fail-closed (a record that cannot
      be cleared could execute a write twice, so a failed clear surfaces as a
      retryable storage error instead of proceeding), then a continuation turn runs
      through the normal send_message path. A one-shot, server-side pre-approval
      for exactly the recorded tool lets the re-issued call execute instead of
      parking a second time β€” it is granted only by the resolving handler and never
      readable from the wire, so a client cannot smuggle a confirmation bypass into
      a frame.
    • Denied β†’ the record is retired and the confirm is acked; the parked tool
      never runs anywhere (a dead park cannot execute, and a still-parked twin on
      another pod resolves to its timeout rejection).
    • Records expire on the same 300s clock as the in-process park, so a
      pod-death orphan cannot authorize a stale write later.

    The same-pod path is unchanged (sender fed, turn resumes in place) except that
    it now also retires the durable record immediately on resolution.

    rust/smooth-operator-server/tests/durable_confirmation.rs drives the real
    handle_frame on TWO AppStates sharing one storage adapter β€” the same
    two-instance shape as the session-registry fix. The approval test asserts its
    premise (pod B holds no live park), that the continuation actually executes the
    gated tool WITHOUT a second write_confirmation_required, and that the record
    is retired; the decline test asserts retire-without-a-turn; the negative
    control proves NO_PENDING_CONFIRMATION is still reachable with no record, so
    the positive tests ride on the record path and nothing else. Positive control:
    with the durable fallback disabled, both cross-instance tests fail reproducing
    the exact production error, while the negative control still passes.

    No wire-protocol change.

@smooai/smooth-operator-web-chat-example@0.0.118

Patch Changes

  • Updated dependencies [b3ad578]
    • @smooai/smooth-operator@1.58.5

@brentrager
brentrager force-pushed the changeset-release/main branch from fd39610 to 64358a3 Compare August 26, 2026 00:08
@brentrager
brentrager merged commit 92017cc into main Aug 26, 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