Changelog

What we shipped to the SDK.

Every release that changes how you log, replay, or store episodes. SDK calls, ingest pipeline, storage, portal — the surfaces a developer touches. Marketing-site changes land on the team blog instead.

  1. SDK 0.1.0a2, R2 storage, and portal polish

    A long day of shipping. Storage went from local-only to a real Cloudflare R2 bucket behind signed URLs, the SDK earned its first OpenTelemetry release, and the portal closed three of its biggest day-1 friction points.

    • SDK 0.1.0a2 · OpenTelemetry trace correlation · New optional [otel] extra (opentelemetry-api only — no heavy SDK). When the SDK detects an active span, it attaches trace_id / span_id / traceparent to every start_episode call. Server validates the W3C trace-context shape and persists it on the episode. The portal episode page renders a Tracing card with copy buttons and an optional one-click 'Open trace' deep-link via NEXT_PUBLIC_TRACE_URL_TEMPLATE (Datadog, Honeycomb, Grafana Tempo, Jaeger). Zero new kwargs — turn it on by installing the extra.
    • Cloudflare R2 wired end-to-end · Episode bytes (.mp4, .npz, .parquet) now flow from the SDK straight to a real R2 bucket via signed PUT URLs minted by the ingest route. The bucket stays private — the DB stores canonical R2 object keys, and a new /api/episodes/[id]/artifact/[kind] route handler mints fresh 1-hour signed GET URLs on every read, gated by the caller's tenant.
    • Episode delete in portal + admin · Three-dot row menu on the episode list (and a matching admin variant) with Archive / Restore / Delete. Delete uses a type-DELETE confirmation dialog to make accidental loss expensive. Note: bytes in R2 are not yet swept — the row-delete clears the DB record only. A reaper worker is on the roadmap.
    • Demo episode for empty portal · First-time-approved users used to land on 'No episodes yet'. They now land on the same empty state, but the preview row is a real clickable Sample run — clicking opens a canonical, read-only sample episode with a synthetic pick-and-place video. Implemented as a sentinel-UUID short-circuit at three boundaries (list page, detail page, artifact resolver) — no migration, no fake DB row, gated behind DEMO_EPISODE_VIDEO_KEY so unseeded deployments can't ship a broken player.
    • Profile vs. Workspace · Settings used to have one editable name field that — silently — also wrote to the workspace name when the caller was the owner. So 'Acme Robotics' became both your personal name (greeting: 'Good afternoon Acme') and your workspace label. The two are now split into a Profile card (personal display name) and a Workspace card (owner-only rename), with clear copy explaining which is which.
  2. ROS 2 adapter — rosbag2 in, episode out

    • ROS 2 adapter (rosbag2 → episode) · The packages/sdk-python [ros2] extra is no longer empty. New scan_bag / encode_bag / upload_bag helpers walk a rosbag2 directory, encode camera topics to .mp4 with OpenCV, and hand the result to the same upload pipeline the rest of the SDK uses. ROS 2 humble + jazzy supported, no rclpy at runtime so you can read bags without a sourced ROS environment.