Recursive AI

Live attach

All onescope docs

A viewer connects to a probe (see probe-wire.md) and turns its stream into a source that the history re-simulates locally.

  1. ProbeFinder.List lists the running probes: socket path, module id, library version, format version and process id.
  2. LiveSession.Connect connects, reads the handshake, asks for the stream and reads the snapshot. The host takes the snapshot at its next recorded step, so it blocks for as long as that takes (up to timeoutMilliseconds, default 5000); the shell runs it on a worker thread so its window keeps drawing (attach returns connecting and sources.attaching shows it). maxRecordBytes (default 256 MiB, each record counted with LiveSession.RecordOverheadBytes) bounds what the viewer keeps: past it Pump stops, Capped is true and the connection closes. It finds the loaded module whose id the handshake names; that module must implement ILiveModule (in the SDK, OneScope.Sdk, so one module serves files and live streams).
  3. ILiveModule.OpenLive gets the library version, the format version and the snapshot, and returns an ILiveSource: a source whose world starts at the snapshot and whose recording is writable, with Recording.StartStep set to the host's step at the snapshot.
  4. A reader thread receives frames into a bounded queue. LiveSession.Pump, on the thread that owns the history, hands each record to ILiveSource.AppendRecord, which appends to the recording. The history sees new steps as they arrive. If the viewer stops pumping the queue fills, the reader waits, and the host's probe drops the viewer.

A live history starts at the host's step at the attach (History.StartStep) and its step numbers are the host's, so the viewer's hash at step s equals the host's hash at step s bit for bit. Seeking, forking and diffing work as for a file. Saving a live source writes a replay that starts from the snapshot, so a session reopens to the same hashes.

In the app, attach connects (by pid or socket) and makes the stream a source. The shell moves arrived records into the history on its own thread (every operation, and every frame of a window), so the history grows while the user scrubs. A live source has a follow flag: on, the shared cursor moves to the host's newest step as records arrive; seeking off the newest step turns it off, seeking to it (or follow with on) turns it on. sources shows live {state, follow, firstStep, newestStep}; when the stream ends (the host closed its probe, dropped a slow viewer, exited or sent bad bytes) the source stays, with what was received, and state says why.

When the host disconnects the viewer, closes its probe, or dies, LiveSession.State says which (Disconnected, Ended) and everything already received stays usable. Attaching again makes a new session from a fresh snapshot.

A OnePhysics host

samples/PhysicsHost is a small program that hosts a OnePhysics world (2D or 3D) behind a probe: physicshost <2d|3d> <steps> <delay-ms> <hash-file>. The world records itself with world.StartRecording(feed), where feed is the OnePhysics module's LiveFeedStream; feed.Record is set to the probe's Record and the probe's snapshot source calls feed.WriteSnapshot. The host also calls probe.Poll() after each step so a viewer that attaches while nothing is being recorded still gets its snapshot. It writes step hash lines when it ends; a viewer's hashes at the same step numbers are equal, whenever it attached.