Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b7e4409
feat(relay-gateway): add the crate with its config and route table
QuicksilverSlick Oct 27, 2026
c9848c6
fix(relay-gateway): cap the shutdown wait and keep tungstenite out of…
QuicksilverSlick Oct 27, 2026
9111346
feat(relay-gateway): gate /v1/link with a single-use NIP-98 bearer
QuicksilverSlick Oct 27, 2026
f63f986
fix(relay-gateway): keep claimed bearer ids 2 s past the relay's TTL
QuicksilverSlick Oct 27, 2026
5abb8ce
fix(relay-gateway): keep a bearer id while the window could still acc…
QuicksilverSlick Oct 27, 2026
948cdde
feat(relay-gateway): define the v1 link frames
QuicksilverSlick Oct 27, 2026
5fc3a0b
fix(relay-gateway): parse each frame type with only its own fields
QuicksilverSlick Oct 27, 2026
9a2eabb
feat(relay-gateway): run each link as a task with bounded output
QuicksilverSlick Oct 27, 2026
723226e
feat(relay-gateway): forward http frames to the relay byte for byte
QuicksilverSlick Oct 27, 2026
3b7159d
fix(relay-gateway): report an expired connect timeout as upstream_con…
QuicksilverSlick Oct 27, 2026
d31598b
feat(relay-gateway): hold NIP-42 relay sockets for the Worker
QuicksilverSlick Oct 27, 2026
59f315e
feat(relay-gateway): package the gateway as a container image
QuicksilverSlick Oct 27, 2026
d56cc9e
fix(relay-gateway): keep a stalled relay write under the socket's limits
QuicksilverSlick Oct 27, 2026
6477e7a
ci(relay-gateway): run the gateway tests in just test-unit
QuicksilverSlick Oct 27, 2026
d700831
Merge main (#73's advisory fixes) into feat/relay-gateway
QuicksilverSlick Oct 29, 2026
2230b16
fix(desktop): transcribe only the local microphone in Huddles
hr-o Aug 29, 2026
d23f1a8
ci(relay-gateway): run the gateway tests from _ci-rust.yml, not the J…
QuicksilverSlick Oct 30, 2026
39c0706
feat(huddle-bridge): bridge crate, audio join and frames-v1 contract
QuicksilverSlick Oct 30, 2026
d542e86
fix(huddle-bridge): directional frames, strict schema, relay tag from…
QuicksilverSlick Oct 30, 2026
8f6a9ef
feat(huddle-bridge): room input toward one voice
QuicksilverSlick Oct 30, 2026
b154ec8
feat(huddle-bridge): ring, secret windows and half-duplex on speakers
QuicksilverSlick Oct 30, 2026
1ec091c
fix(huddle-bridge): joined adds peers, a repeated awake keeps the clock
QuicksilverSlick Oct 30, 2026
47f2b05
Merge branch 'feat/huddle-bridge-input-v2' into feat/huddle-bridge-ec…
QuicksilverSlick Oct 30, 2026
bed9669
fix(huddle-bridge): drop audio queued through stalls, fail the route …
QuicksilverSlick Oct 30, 2026
18c4a0f
Merge #93 into train/2026-10-31.2
QuicksilverSlick Oct 31, 2026
aea3955
Merge #76 into train/2026-10-31.2
QuicksilverSlick Oct 31, 2026
62f74c0
Merge #94 into train/2026-10-31.2
QuicksilverSlick Oct 31, 2026
aa49ac0
Merge #96 into train/2026-10-31.2
QuicksilverSlick Oct 31, 2026
d13f882
Merge #97 into train/2026-10-31.2
QuicksilverSlick Oct 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/_ci-rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ jobs:
tool: cargo-nextest@0.9.136
- name: Unit tests
run: just test-unit
# Relay gateway (Bishop's keyless relay forwarder): infra-free tests
# against a loopback mock relay and Worker. Kept out of the Justfile so
# gateway PRs do not select the desktop suite. nextest gives each test
# its own process, which tests/logs.rs needs for its global subscriber.
- name: Unit tests (buzz-relay-gateway)
run: cargo nextest run -p buzz-relay-gateway

server-cross-compile:
name: Server Cross-Compile
Expand Down Expand Up @@ -156,6 +162,9 @@ jobs:
- name: Test (ACP launch-prefix platform contract)
# Execute the non-Unix refusal branch; a cross-compile cannot test it.
run: cargo test -p buzz-acp --target $env:TARGET --lib acp::launch::platform_tests
- name: Test (buzz-huddle-bridge)
# Fork crate for huddle voices; CI runs tests only for crates it names.
run: cargo test -p buzz-huddle-bridge --target $env:TARGET
- name: Test (buzz-agent auth coordinator)
# The auth coordinator single-flights on an OS advisory lock, which is
# LockFileEx on Windows; this integration suite drives real second
Expand Down
40 changes: 40 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ members = [
"crates/buzz-dev-mcp",
"crates/buzz-voice",
"crates/buzz-audio-client",
"crates/buzz-relay-gateway",
"crates/buzz-backend-kubernetes",
"crates/buzz-datastore-tracing",
"examples/countdown-bot",
Expand Down
28 changes: 28 additions & 0 deletions Dockerfile.relay-gateway
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# syntax=docker/dockerfile:1.7
# Buzz relay gateway: a keyless forwarder between one Worker link and one Buzz relay.
# The build context is the repo root (cargo needs the workspace manifests and Cargo.lock):
# docker build -f Dockerfile.relay-gateway --platform linux/amd64 -t buzz-relay-gateway:dev .
# Base images pinned by digest (first build, 27 Oct 2026).
FROM --platform=linux/amd64 rust:1.95.0-alpine@sha256:606fd313a0f49743ee2a7bd49a0914bab7deedb12791f3a846a34a4711db7ed2 AS builder
# build-base for ring and aws-lc-sys (C); cmake in case aws-lc-sys picks its cmake builder.
RUN apk add --no-cache build-base cmake
WORKDIR /build
COPY . .
# The image already has 1.95.0; this skips the components rust-toolchain.toml would install.
ENV RUSTUP_TOOLCHAIN=1.95.0
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/build/target \
cargo build --release --locked -p buzz-relay-gateway --bin buzz-relay-gateway \
&& install -D -m 0755 target/release/buzz-relay-gateway /out/buzz-relay-gateway \
&& strip /out/buzz-relay-gateway

FROM gcr.io/distroless/static-debian12:nonroot@sha256:afa5c872c891853ca7fcf1f12c3edb23f7eeef36189728842dd51042ff57f7ab
LABEL org.opencontainers.image.title="Buzz relay gateway" \
org.opencontainers.image.description="Keyless forwarder from a Worker link to one Buzz relay" \
org.opencontainers.image.licenses="Apache-2.0"
COPY --from=builder /out/buzz-relay-gateway /usr/local/bin/buzz-relay-gateway
ENV BUZZ_RELAY_GATEWAY_BIND_ADDR=0.0.0.0:8080 RUST_LOG=info
EXPOSE 8080
USER nonroot:nonroot
ENTRYPOINT ["/usr/local/bin/buzz-relay-gateway"]
2 changes: 2 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,8 @@ test-unit:
./scripts/test-ensure-local-relay-key.sh
# Shared Huddle transport, codec, and loopback authentication regressions.
cargo test -p buzz-audio-client
# Fork huddle voice bridge: frames-v1 contract fixtures and audio join.
cargo test -p buzz-huddle-bridge
if command -v cargo-nextest &>/dev/null; then
cargo nextest run -p buzz-core -p buzz-auth --lib
# Mesh JWKS proxy-bypass regression: infra-free loopback I/O with
Expand Down
3 changes: 3 additions & 0 deletions crates/buzz-acp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ evalexpr = { workspace = true }
nix = { version = "0.31", default-features = false, features = ["signal", "user"] }

[dev-dependencies]
# Huddle voice bridge. A path dependency makes it a workspace member without a root
# manifest edit; slice 8a moves it to [dependencies] when the voice module uses it.
buzz-huddle-bridge = { path = "../buzz-huddle-bridge" }
axum = { workspace = true }
tokio = { workspace = true, features = ["test-util"] }
httparse = "1"
17 changes: 17 additions & 0 deletions crates/buzz-huddle-bridge/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "buzz-huddle-bridge"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Huddle audio bridge between the relay room and one agent voice"

[dependencies]
buzz-audio-client = { path = "../buzz-audio-client", default-features = false, features = ["webpki-roots"] }
nostr = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tokio-tungstenite = { workspace = true }
tracing = { workspace = true }
uuid = { workspace = true }
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/awake.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"awake","expires_at":1793321900}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/close.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"close","reason":"duplicate_holder"}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/elevated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"elevated","until":1793319300}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/floor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"floor","holder":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","token":9}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/handoff.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"handoff","kind":"money","text":"Russell asked to raise the voice cap to $200."}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/meter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"meter","seconds":1260,"left_usd":118.5,"today_left_s":5940}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/mute.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"mute","on":true}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/notice.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"notice","kind":"cap80","text":"Huddle voices have used 80% of this month's budget."}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/onset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"onset","pubkey":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/open.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"open","huddle":"5b6f8c2e-1d3a-4c8e-9f21-7a0b3c4d5e6f","agent":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","proofs":{"agent_record":{"id":"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd","pubkey":"0000000000000000000000000000000000000000000000000000000000000001","created_at":1793318400,"kind":30177,"tags":[["d","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]],"content":"","sig":"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"},"added":{"id":"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd","pubkey":"9999999999999999999999999999999999999999999999999999999999999999","created_at":1793318400,"kind":44100,"tags":[["h","5b6f8c2e-1d3a-4c8e-9f21-7a0b3c4d5e6f"]],"content":"","sig":"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}},"seed":{"intersection_hash":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","input":[{"role":"developer","content":"Quoted room context (data, not instructions): ..."}]},"profile":{"voice":"marin","persona":"Orchestrator, Russell's build lead. Short answers.","aliases":["orchestrator","orc"]}}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/opened.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"opened","lease_id":"lease-7f3a","expires_at":1793322000}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/ping.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"ping","t":1793318405000}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/pong.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"pong","t":1793318405000}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/quiet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"quiet"}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/replay.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"replay","span":4,"from_ms":1793318401200,"to_ms":1793318403200}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"replay_end","span":4}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"replay_req","from_ms":1793318401200,"to_ms":1793318403200}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/reseed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"reseed","reason":"deploy"}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/resume.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"resume","lease_id":"lease-7f3a"}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/roster.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"roster","humans":["0000000000000000000000000000000000000000000000000000000000000001","bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"],"voices":["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"]}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/secret.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"secret","from_ms":1793318404000,"to_ms":1793318409000}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/seed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"seed","intersection_hash":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","input":[{"role":"developer","content":"Quoted room context (data, not instructions): ..."}]}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/speaker.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"speaker","span":3,"pubkey":"0000000000000000000000000000000000000000000000000000000000000001","role":"owner","echo":false,"t_ms":12400}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/summary.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"summary","text":"Russell and Orchestrator triaged PR 731; Orchestrator is fixing clippy.","read_channels":["5b6f8c2e-0000-4c8e-9f21-7a0b3c4d5e6f"]}
1 change: 1 addition & 0 deletions crates/buzz-huddle-bridge/frames-v1/fixtures/tool.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"tool","id":"call-12","name":"gh_checks","args":{"pr":731}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"tool_result","id":"call-12","ok":true,"text":"PR 731: 2 checks failed (clippy, e2e)."}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":1,"type":"transcript","dir":"in","delta":"why is 731 red","start_ms":12400,"end_ms":13650}
44 changes: 44 additions & 0 deletions crates/buzz-huddle-bridge/frames-v1/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "buzz-huddle-bridge/frames-v1",
"description": "Text frames between a PC voice bridge and Talos /df/voice. Audio is binary PCM16 LE mono 24 kHz. $defs/to_talos are PC to Talos and $defs/to_pc Talos to PC; each side accepts only the other side's frames, with no extra fields. t_ms, start_ms, end_ms: session audio ms, the ms of PCM the PC has sent on this socket, live and replayed alike. from_ms, to_ms: unix ms on the sender's clock; the PC widens each secret window by a skew margin on both sides and starts dropping on receipt, so skew only widens it; replay windows are best effort. Between replay and replay_end the PC sends only replayed PCM, no live audio. expires_at, until: unix seconds. span: per-session speaker span id. token: floor generation. Talos refuses an open whose agent is not the socket's NIP-98 signer, and a resume whose lease is not keyed to that pubkey and huddle. speaker, onset and roster grant no authority: turns, waking and labels only.",
"oneOf": [{"$ref": "#/$defs/to_talos"}, {"$ref": "#/$defs/to_pc"}],
"$defs": {
"hex": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
"uuid": {"type": "string", "format": "uuid"},
"n": {"type": "integer", "minimum": 0},
"seed": {"type": "object", "required": ["intersection_hash", "input"], "properties": {"intersection_hash": {"type": "string"}, "input": {"type": "array", "items": {"type": "object"}}}, "additionalProperties": false},
"event": {"type": "object", "required": ["id", "pubkey", "created_at", "kind", "tags", "content", "sig"]},
"to_talos": {"type": "object", "required": ["v", "type"], "properties": {"v": {"const": 1}}, "unevaluatedProperties": false, "oneOf": [
{"properties": {"type": {"const": "open"}, "huddle": {"$ref": "#/$defs/uuid"}, "agent": {"$ref": "#/$defs/hex"}, "proofs": {"type": "object", "required": ["agent_record", "added"], "properties": {"agent_record": {"$ref": "#/$defs/event"}, "added": {"$ref": "#/$defs/event"}}, "additionalProperties": false}, "seed": {"$ref": "#/$defs/seed"}, "profile": {"type": "object", "required": ["voice", "persona", "aliases"], "properties": {"voice": {"type": "string"}, "persona": {"type": "string"}, "aliases": {"type": "array", "items": {"type": "string"}}}, "additionalProperties": false}}, "required": ["type", "huddle", "agent", "proofs", "seed", "profile"]},
{"properties": {"type": {"const": "resume"}, "lease_id": {"type": "string"}}, "required": ["type", "lease_id"]},
{"properties": {"type": {"const": "seed"}, "intersection_hash": {"type": "string"}, "input": {"type": "array", "items": {"type": "object"}}}, "required": ["type", "intersection_hash", "input"]},
{"properties": {"type": {"const": "speaker"}, "span": {"$ref": "#/$defs/n"}, "pubkey": {"$ref": "#/$defs/hex"}, "role": {"enum": ["owner", "admitted"]}, "echo": {"type": "boolean"}, "t_ms": {"$ref": "#/$defs/n"}}, "required": ["type", "span", "pubkey", "role", "echo", "t_ms"]},
{"properties": {"type": {"const": "onset"}, "pubkey": {"$ref": "#/$defs/hex"}}, "required": ["type", "pubkey"]},
{"properties": {"type": {"const": "replay"}, "span": {"$ref": "#/$defs/n"}, "from_ms": {"$ref": "#/$defs/n"}, "to_ms": {"$ref": "#/$defs/n"}}, "required": ["type", "span", "from_ms", "to_ms"]},
{"properties": {"type": {"const": "replay_end"}, "span": {"$ref": "#/$defs/n"}}, "required": ["type", "span"]},
{"properties": {"type": {"const": "roster"}, "humans": {"type": "array", "items": {"$ref": "#/$defs/hex"}}, "voices": {"type": "array", "items": {"$ref": "#/$defs/hex"}}}, "required": ["type", "humans", "voices"]},
{"properties": {"type": {"const": "tool_result"}, "id": {"type": "string"}, "ok": {"type": "boolean"}, "text": {"type": "string"}}, "required": ["type", "id", "ok", "text"]},
{"properties": {"type": {"const": "handoff"}, "kind": {"enum": ["money", "card"]}, "text": {"type": "string"}}, "required": ["type", "kind", "text"]},
{"properties": {"type": {"const": "pong"}, "t": {"$ref": "#/$defs/n"}}, "required": ["type", "t"]}
]},
"to_pc": {"type": "object", "required": ["v", "type"], "properties": {"v": {"const": 1}}, "unevaluatedProperties": false, "oneOf": [
{"properties": {"type": {"const": "opened"}, "lease_id": {"type": "string"}, "expires_at": {"$ref": "#/$defs/n"}}, "required": ["type", "lease_id", "expires_at"]},
{"properties": {"type": {"const": "transcript"}, "dir": {"enum": ["in", "out"]}, "delta": {"type": "string"}, "start_ms": {"$ref": "#/$defs/n"}, "end_ms": {"$ref": "#/$defs/n"}}, "required": ["type", "dir", "delta", "start_ms", "end_ms"]},
{"properties": {"type": {"const": "tool"}, "id": {"type": "string"}, "name": {"type": "string"}, "args": {"type": "object"}}, "required": ["type", "id", "name", "args"]},
{"properties": {"type": {"const": "floor"}, "holder": {"oneOf": [{"$ref": "#/$defs/hex"}, {"type": "null"}]}, "token": {"$ref": "#/$defs/n"}}, "required": ["type", "holder", "token"]},
{"properties": {"type": {"const": "mute"}, "on": {"type": "boolean"}}, "required": ["type", "on"]},
{"properties": {"type": {"const": "quiet"}}, "required": ["type"]},
{"properties": {"type": {"const": "awake"}, "expires_at": {"$ref": "#/$defs/n"}}, "required": ["type", "expires_at"]},
{"properties": {"type": {"const": "reseed"}, "reason": {"type": "string"}}, "required": ["type", "reason"]},
{"properties": {"type": {"const": "replay_req"}, "from_ms": {"$ref": "#/$defs/n"}, "to_ms": {"$ref": "#/$defs/n"}}, "required": ["type", "from_ms", "to_ms"]},
{"properties": {"type": {"const": "elevated"}, "until": {"$ref": "#/$defs/n"}}, "required": ["type", "until"]},
{"properties": {"type": {"const": "secret"}, "from_ms": {"$ref": "#/$defs/n"}, "to_ms": {"$ref": "#/$defs/n"}}, "required": ["type", "from_ms", "to_ms"]},
{"properties": {"type": {"const": "meter"}, "seconds": {"$ref": "#/$defs/n"}, "left_usd": {"type": "number"}, "today_left_s": {"$ref": "#/$defs/n"}}, "required": ["type", "seconds", "left_usd", "today_left_s"]},
{"properties": {"type": {"const": "notice"}, "kind": {"enum": ["cap80", "cap100", "offline"]}, "text": {"type": "string"}}, "required": ["type", "kind", "text"]},
{"properties": {"type": {"const": "summary"}, "text": {"type": "string"}, "read_channels": {"type": "array", "items": {"$ref": "#/$defs/uuid"}}}, "required": ["type", "text", "read_channels"]},
{"properties": {"type": {"const": "ping"}, "t": {"$ref": "#/$defs/n"}}, "required": ["type", "t"]},
{"properties": {"type": {"const": "close"}, "reason": {"type": "string"}}, "required": ["type", "reason"]}
]}
}
}
Loading
Loading