octoturgeandClaude Opus 5 9b8f0c2308 Carry camera stream information on the edge protocol
Two optional fields so a user can be pointed at a printer's camera.

`hello.stream_base_url` is where the gateway serves restreams - the base of
the go2rtc instance it already supervises. Reported by the gateway rather
than configured in the cloud, because only the gateway knows the address it
is actually reachable at.

That address is a LAN one, and the schema says so where someone will read it
rather than leaving it to be discovered in a support ticket. A browser on the
same network as the gateway can play the stream; one outside it cannot, and
the relay that would fix it does not exist. For a print farm whose operator
is in the workshop this is the normal case and it works; for anyone else it
is a limit, and anything surfacing the field has to cope with it being
unreachable.

`printer_telemetry.camera_stream` is the stream's name, present only when
there is one. Absent is the common answer today and the reason is worth
recording: a Bambu P1/A1 publishes no RTSP URL at all - a real P1P's ipcam
block carries `ipcam_dev` and `ipcam_record` and nothing to connect to -
while an H2C reports `rtsps://<ip>:322/streaming/live/1`. So RTSP restreaming
covers the X1/H2 class and nothing else; the rest need Bambu's proprietary
port-6000 JPEG stream, which is a client no gateway has yet.

Both optional and additive, so existing gateways are unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-15 22:55:52 +00:00

continuum-schemas

Single source of truth for the Continuum data model. Everything here is JSON Schema, compiled into two consumer packages:

  • packages/ts-types - hand-written TypeBox schemas under src/schemas/ used for runtime validation in continuum-backend's ElysiaJS routes.
  • packages/rust-types - a Rust crate (continuum-rust-types) with hand-written, serde-derived structs for continuum-proxy and continuum-ai-worker.

Layout

schemas/continuum/v1/     Continuum's own model
  ai/                     continuum-backend <-> continuum-ai-worker: the
                          stream:camera_frames work queue and the
                          channel:print_alerts notification channel
  edge/                   continuum-backend <-> continuum-proxy: the
                          /ws/edge/v1 gateway uplink protocol
  material/  printer/     domain objects
  vendor.schema.json
schemas/bambulab/         Bambu Lab MQTT wire schemas (v1/v2, report + request)
packages/ts-types/        TypeBox schemas (hand-written, mirrors schemas/)
packages/rust-types/      serde structs (hand-written, mirrors schemas/)

The two inter-service protocols - edge/ and ai/ - are here for a specific reason: each has two independent implementations, one per repo, and when there was nothing written down between them they drifted completely while every test passed. /ws/edge/v1 had an auth handshake the gateway never sent; stream:camera_frames had a producer writing printerId and a consumer reading printer_id, so every frame was attributed to a printer called "unknown". Neither failure was visible from either side alone, which is what a canonical schema plus a contract test on each end is for.

schemas/continuum/v1/*.schema.json is the canonical shape for each domain object; packages/ts-types/src/schemas/ and packages/rust-types/src/lib.rs both mirror it by hand. A mirror is added per schema only once something actually consumes it, so not every file here has one, and the two inter-service protocols keep their Rust mirror in the single repo that consumes it rather than in packages/rust-types: edge/ in continuum-proxy/src/uplink/protocol.rs, ai/ in continuum-ai-worker/src/task.rs. The set is small and changes slowly, which is why keeping hand-synced copies in sync is less overhead than a codegen pipeline (protoc/ts-proto/prost-build) nothing actually consumed - see git history for the protobuf version this replaced, and why it was dropped: every service in this system talks JSON (JSON Schema for the wire, TypeBox/serde for runtime validation), so protobuf's actual value - a single schema compiled into a compact binary wire format for both languages - never applied.

Whenever a domain schema changes, update all three by hand: the JSON Schema file, the TypeBox schema, and the Rust struct.

Build / verify

Requires npm install at the repo root, and a Rust toolchain, first.

npm install
npm run build:rust   # cargo build, confirms the Rust structs compile
npm run typecheck     # tsc -b, confirms the TypeBox schemas compile

There's no build:ts step - the TS side is hand-written, not generated.

S
Description
Continuum platform: continuum-schemas
Readme
319 KiB
Languages
TypeScript 100%