thread.item_posted), a record has one shape with a source,
events are read by id instead of by time, and the WebSocket carries listeners instead of subscriptions. The model is
described in Session Events; this page maps the old names to the new.
There is no compatibility period. The backend, the worker, the CLI, the SDK and the web app moved together. A client
installed before the cutover stops reading events until it is upgraded: the old commands and frames are gone, not
deprecated. Upgrade every BlobHub client you run, the worker, the CLI and the SDK, to its current release.
History was migrated. Stored session events kept their time and were renamed to the new types, and their source.kind
is unknown, since the old rows did not say what caused them. Event ids are new: an id or cursor saved from before
the cutover no longer resolves. Expired rows, rows of deleted sessions, rows of an unknown type and malformed rows
were not migrated. execution_started and execution_ended were realtime frames only and never stored, so migrated
history holds no execution.* records.
The execution log was moved to a new table, and each of its rows kept its message, attributes and data as they
were, so a data_id still downloads. Two things differ for a reader of list_execution_events: every migrated row has
a new id (the old one is not served) and a source with kind unknown, and created_at is written with six
fractional digits. The event types, flow.* and processor.*, are unchanged.
Types
The stream also raises types that had no old name:
session.created, session.updated, session.reopened,
execution.created and execution.stop_requested.
Parameters and keys
Executions now expose a public
source, {kind, user_id?, listener?, client?, depth}, on get_execution,
list_executions and create_execution. No earlier response carried a field for it. An existing execution whose
internal trigger was api or scheduler carries the matching source, {kind: "api", depth: 0} or
{kind: "scheduler", depth: 0}; one with any other trigger was left without a source.
created_since is unchanged on list_session_thread_items.
WebSocket
listener/add returns a listener_id, and each listener/event frame carries it with the whole event record in
event; the frame no longer repeats the scope and target. A repeated subscription/add for the same session merged
its types into one subscription; each listener/add now creates its own listener, so keep every listener_id. See
Listener.
What to change in your code
A poll loop. Before, a time cursor:events. Keep the last id you held, and every so often re-read from the boundary id of a
timestamp a minute older, dropping ids you already have.
A subscription. Before:
session_deleted handler. Before, the type was read from the frame’s params:
params.event.type equal to session.deleted. Add a filter of {"types": ["session.deleted"]} to receive
only that type, and remember that the listeners of a deleted session are removed once the event is pushed.
