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.
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 undersrc/schemas/used for runtime validation incontinuum-backend's ElysiaJS routes.packages/rust-types- a Rust crate (continuum-rust-types) with hand-written,serde-derived structs forcontinuum-proxyandcontinuum-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.