SIGN IN SIGN UP

feat(channel): add Jade cloud relay channel for remote control

Add JadeRelayChannel implementing MessageChannel, mirroring the
Telegram/Discord channels: it long-polls the Jade relay for `prompt`
events, injects them into the live ambient session via
inject_message, and posts the agent's reply back as a `response`
event for the cloud client to read.

Unlike the WebSocket gateway, nothing listens on the laptop: the
client only makes outbound long-poll requests, so there is no inbound
port to attack. Auth is a bearer token plus optional x-jade-token-id
header; channel scope is user_id/session_id.

- SafetyConfig: jade_relay_* fields (api_base, token, token_id,
  user_id, session_id, enabled, reply_enabled), all serde(default).
- env overrides: JCODE_JADE_RELAY_* (token implies enabled).
- ChannelRegistry::from_config registers the channel when enabled and
  api_base/token/session_id are all present (otherwise warns + skips).
- Heartbeats register the device every 30s; init poll seeds the cursor
  so existing history is not replayed.
- Handles permission-approval replies via record_permission_via_file,
  matching the Telegram path.

Tests: unit tests for event parsing, URL encoding/join, and registry
wiring; an ignored live roundtrip test (prompt -> poll -> response)
that runs against the real relay with JADE_RELAY_* env vars set.
Verified live against the dev relay: roundtrip OK.
J
jeremy committed
aa5f629e85512a1846c18ccf0e06e362948402ca
Parent: 2e64f51