π¦ New version release - #553
Merged
Merged
Conversation
brentrager
force-pushed
the
changeset-release/main
branch
from
August 26, 2026 00:32
ae76e05 to
e3bd531
Compare
brentrager
force-pushed
the
changeset-release/main
branch
from
August 26, 2026 00:55
e3bd531 to
de806a0
Compare
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.
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.6
Patch Changes
512cb01: fix(server): a prod failure is diagnosable from logs alone (th-694c22)
A live "session not found" incident produced ZERO server log lines β chat-ws
emitted one line in six hours of continuous traffic, because the server's
decision points were silent: every one of the ~30
protocol::error(...)emitsites sent the client-visible error frame without logging, and the session
read-through, confirmation/interaction parks and resolves, OTP verification,
and turn starts logged nothing at info.
One warn at the single error-frame construction site now covers every
client-visible failure, present and future (the frame's human text rides as
detailβmessageis tracing's reserved event-message field). Info linesland at the decision points an incident responder actually needs: session
primed from storage (the cross-pod resume working as designed), turn requested
(session + requestId), confirmation parked / live-resolved / durably resolved,
interaction parked / resolved-with-values, and OTP verified. No debug spam β
one line per event that changes state.
e0d4213: fix(server): a pending Rich Interaction survives the pod that parked it (th-db0816)
The interaction sibling of the durable-confirmation fix. A raise's park is a
channel into a turn on ONE pod, so a visitor whose refresh reconnected them to
another replica β or whose pod rolled β got
NO_PENDING_INTERACTIONfor thecard they were just shown, and the identity they typed evaporated.
The interaction bridge now persists every raise into the session's durable
metadata.pendingInteraction(interaction id + kind + spec β the fullvalidation contract), retired when the turn ends.
submit_interactionwith nolive park validates against that record exactly as it would against the park
(mismatched
interactionIdstill rejected, per-field validation still routedto the kind's server-side validator, invalid submits leave the record for a
retry) and resolves it there: submitted values retire the record fail-closed
and then run the kind's host effect; declined retires it with an ack. No
continuation turn β the host effect is the durable outcome, and a dead raise's
model acknowledgment is forgone rather than fabricated.
attach_session_identitynow also writes through to storage: a capturedcontact (name/email/phone) used to live only in one pod's map, so any pod roll
forgot a visitor who had just introduced themselves β even on the same pod.
Two-instance tests (
tests/durable_interactions.rs) drive the realhandle_frameon twoAppStates over one storage adapter: submit-on-the-other-pod attaches the identity durably and retires the record, decline retires it,
mismatched ids are still rejected, and the negative control proves
NO_PENDING_INTERACTIONis still reachable with no record. Positive control:with the durable read disabled, both cross-instance tests fail reproducing the
production error while the negative control still passes.
No wire-protocol change.
2904a8a: feat(server): a host can install the turn's
AgentExecutorβ the missing seam on the emitted replyTurnRequest::executorhas been a public field since ADR-030, andrunner::turn_executorhas always honored it, but the server's soleTurnRequestconstruction site (handler.rs) hardcodedexecutor: None. So theseam existed on paper and was unreachable in practice: nothing outside this crate
could supply one.
That gap is what left chat-ws with no host-side seam on the emitted text. When the
runner owns the whole turn and streams plain text from inside the published crate,
a host has no point at which to inspect what the agent said next to what it
actually did β so the TS general agent's post-response guard (which STRIPPED an
escalation claim when
notify_humanshad not fired) and the voice stall-replyretry had nowhere to run. The consequence was live: an agent could tell a customer
"I've passed it along" with nothing behind it, and the only available fix was
prompt prevention, not enforcement.
AppState::with_executorinstalls one, and the handler passes it onto every turn.Two things arrive through it:
InProcessExecutorand theninspects or edits the returned
Conversationbefore the runner reads its finalassistant message.
Conversation.messagesis public and carries the turn's toolcalls, so this is the one place a host can guard a reply against the tools that
actually ran.
One boundary is worth stating plainly rather than discovering later: tokens the
turn streamed have already left over the events channel by the time the
conversation is returned, so an edit here changes the persisted message and the
eventual_responseβ not what already streamed. A decorator that needs the streamtoo can pass its own channel down and forward.
Default behavior is unchanged:
Noneis still the in-process executor, which is averbatim delegation to
Agent::run_with_channel. The lambda flavor keepsNonealongside its other
Noneinjection seams (it has noAppStateto install oneon).
rust/smooth-operator-server/tests/executor_seam.rsdrives the realhandle_frameoffline with an escalation-guard executor and pins both halves: theinstalled executor is the one that runs the turn and its rewrite reaches BOTH the
persisted outbound message and the
eventual_response; with no executor installedthe model's text survives byte-for-byte.
@smooai/smooth-operator-web-chat-example@0.0.119
Patch Changes