Repository navigation
Adds emit-event, an agent tool that makes a realtime event arrive in the running app with no backend, no publish and no network round trip. An automated test can use it to drive the app through a realtime flow.
npx rozenite agent avasapp/ably call --tool emit-event --session <id> \
--args '{"channel":"bid-orders","name":"ride_assignment","data":{"rideId":"r_42"}}'It never publishes
It hands a fabricated Ably.Message straight to the listeners the app itself registered with subscribe(). A real publish would fan the message out to every other client attached to the channel, such as another developer's app or a real device, and it would need the network. Local delivery is safe on a shared channel, works offline, and completes deterministically inside a test.
That also limits what it can do: the app must already have subscribed. delivered: 0 says so, and a note explains whether the channel had no listener at all or every listener filtered the message out. It injects messages only, not presence.
What a call reports
delivered,skipped,failedanderrors. A listener that throws is isolated, as ably-js isolates it, but it is reported rather than swallowed. The other listeners still receive the message.- Async listeners are awaited for up to 2s. A rejected promise is reported like a synchronous throw, and the app has finished reacting before you assert. A listener still running at 2s is counted in
pending. - Filters apply as in Ably. Event-name and
MessageFiltersubscriptions are honoured, and a listener only receives what Ably would have given it. - It is not idempotent. Two calls deliver twice.
In the event stream
Injected events are recorded like any other, marked injected: true and with their summary prefixed. A listing never passes a synthetic event off as one Ably delivered. They are left out of get-stats and the channel's inbound counter, which describe only what Ably delivered. While capture is paused, delivery still happens but nothing is recorded, and the result says so.
Keep data JSON-safe. The listener receives the value you passed, but the recorded event stores a JSON copy. undefined fields vanish from the record and NaN/Infinity become null, with no warning. The bundled ably-devtools skill covers this and the rest of the tool's semantics.
The name is a contract
emit-event is this plugin's implementation of a general capability: deliver an inbound message the app never asked for. Rozenite's AgentToolTraits has no capability field, so a wrapper that treats plugins as interchangeable providers discovers them by probing each domain for a tool named exactly emit-event. The name is a discovery key and will not be renamed. channel, name and data are the generic arguments. An app's own event envelope travels inside data, and the tool never inspects its shape.
Node scripts on @rozenite/agent-sdk get a typed descriptor at ablyTools.emitEvent from @avasapp/rozenite-plugin-ably/sdk.
Upgrading
Nothing to change. Peer ranges are unchanged, and the plugin still requires Rozenite 2.2 or later.
Repo
Development dependencies moved to React 19.2.8, react-native 0.87.1 and lucide-react 1.x (the icon library the panel uses), and CI moved to actions/checkout and actions/setup-node v7.
Full changelog: v1.1.0...v1.2.0