Skip to content

Commit 4e05b01

Browse files
authored
docs: add clarity on use of custom packet type (#12)
1 parent 065df56 commit 4e05b01

File tree

10 files changed

+166
-9
lines changed

10 files changed

+166
-9
lines changed

ROADMAP.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ StreamKit is audio-first today. Video support is a major milestone for v1.0:
111111

112112
- ResourceManager integration for native plugins (unified model caching)
113113
- Plugin API versioning and compatibility checks
114+
- Plugin-defined packet schemas/metadata ("virtual packet types") that surface in `/schema/packets` and the UI while flowing as `Custom(type_id)` at runtime
114115
- Exploration of WASM/Native API convergence
115116

116117
---

apps/skit/src/bin/gen-docs-reference.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,80 @@ fn render_packet_page(entry: &PacketTypeEntry) -> Result<String> {
346346
out.push_str(&format!("Type system: `{}`\n\n", entry.kind_repr));
347347
out.push_str(&format!("Runtime: `{}`\n\n", entry.runtime_repr));
348348

349+
if entry.id == "Custom" {
350+
out.push_str(
351+
r#"## Why `Custom` exists
352+
`Custom` is StreamKit's **extensibility escape hatch**: it lets plugins and pipelines exchange
353+
structured data **without adding new built-in packet variants**.
354+
355+
It was designed to:
356+
357+
- Keep the core packet set small and stable (important for UIs and SDKs).
358+
- Enable fast iteration for plugin-defined events and typed messages.
359+
- Preserve type-checking via `type_id` so pipelines still validate before running.
360+
- Stay user-friendly over JSON APIs (`encoding: "json"` is debuggable and easy to inspect).
361+
362+
## When to use it
363+
Use `Custom` when you need **structured, typed messages** that don't fit existing packet types, for example:
364+
365+
- Plugin-defined events (e.g. VAD, moderation, scene triggers, rich status updates).
366+
- Application-level envelopes (e.g. tool results, routing hints, structured logs).
367+
- Telemetry-like events (see below) that you want to treat as first-class data.
368+
369+
Prefer other packet types when they fit:
370+
371+
- Audio frames/streams: `/reference/packets/raw-audio/` or `/reference/packets/opus-audio/`
372+
- Plain strings: `/reference/packets/text/`
373+
- Opaque bytes, blobs, or media: `/reference/packets/binary/`
374+
- Speech-to-text results: `/reference/packets/transcription/`
375+
376+
## Type IDs, versioning, and compatibility
377+
`type_id` is the **routing key** for `Custom` and is part of the type system.
378+
379+
- Compatibility: `PacketType::Custom { type_id: "a@1" }` only connects to the same `type_id`.
380+
If you truly want "any custom", use `PacketType::Any` on the input pin.
381+
- Versioning: include a major version suffix like `@1` and bump it for breaking payload changes.
382+
- Namespacing: use a stable, collision-resistant prefix (examples below).
383+
384+
Examples used in this repo:
385+
386+
- `core::telemetry/event@1` (telemetry envelope used on the WebSocket bus)
387+
- `plugin::native::vad/vad-event@1` (VAD-style events)
388+
389+
## Payload conventions
390+
`data` is schema-less JSON: treat it as **untrusted input** and validate it in consumers.
391+
392+
For "event"-shaped payloads, a common convention is an `event_type` string inside `data`:
393+
394+
```json
395+
{
396+
"type_id": "core::telemetry/event@1",
397+
"encoding": "json",
398+
"data": { "event_type": "vad.start", "source": "mic" },
399+
"metadata": { "timestamp_us": 1735257600000000 }
400+
}
401+
```
402+
403+
Related docs:
404+
405+
- WebSocket telemetry events: `/reference/websocket-api/#telemetry-events-nodetelemetry`
406+
- Nodes that observe/emit telemetry: `/reference/nodes/core-telemetry-tap/`, `/reference/nodes/core-telemetry-out/`
407+
408+
## When a core packet type is a better fit
409+
`Custom` is great for iteration, but adding a new core packet type can be worth it when:
410+
411+
- The payload is **high-volume / performance-sensitive** (zero-copy, binary codecs, large frames).
412+
- The payload needs **canonical semantics** across the ecosystem (multiple nodes, UIs, SDKs).
413+
- There are **well-defined fields** that benefit from first-class schema/compat rules (not just `type_id`).
414+
- The payload should be **universally inspectable/renderable** in the UI (timelines, previews, editors).
415+
416+
In those cases, open a GitHub issue describing the use case and examples (or send a PR). The goal is to keep
417+
the built-in packet set small and stable, and graduate widely useful patterns out of `Custom` when needed.
418+
419+
"#,
420+
);
421+
}
422+
349423
let registry = streamkit_core::packet_meta::packet_type_registry();
350424
if let Some(meta) = registry.iter().find(|m| m.id == entry.id) {
351425
out.push_str("## UI Metadata\n");

docs/src/content/docs/reference/configuration-generated.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -587,8 +587,7 @@ Telemetry and observability configuration (OpenTelemetry, tokio-console).
587587
"core::sink"
588588
],
589589
"allowed_plugins": [
590-
"plugin::*",
591-
"native::audio*"
590+
"plugin::*"
592591
],
593592
"allowed_samples": [
594593
"oneshot/*.yml",
@@ -1012,8 +1011,7 @@ Telemetry and observability configuration (OpenTelemetry, tokio-console).
10121011
"core::sink"
10131012
],
10141013
"allowed_plugins": [
1015-
"plugin::*",
1016-
"native::audio*"
1014+
"plugin::*"
10171015
],
10181016
"allowed_samples": [
10191017
"oneshot/*.yml",

docs/src/content/docs/reference/nodes/transport-http-fetcher.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
# SPDX-FileCopyrightText: © 2025 StreamKit Contributors
33
# SPDX-License-Identifier: MPL-2.0
44
title: "transport::http::fetcher"
5-
description: "Fetches binary data from an HTTP/HTTPS URL. Security: this is an SSRF-capable node; restrict it via role allowlists. Redirects are disabled (v0.1.0)."
5+
description: "Fetches binary data from an HTTP/HTTPS URL. Security: this is an SSRF-capable node; restrict it via role allowlists. Redirects are disabled (v0.1.x)."
66
---
77

88
`kind`: `transport::http::fetcher`
99

10-
Fetches binary data from an HTTP/HTTPS URL. Security: this is an SSRF-capable node; restrict it via role allowlists. Redirects are disabled (v0.1.0).
10+
Fetches binary data from an HTTP/HTTPS URL. Security: this is an SSRF-capable node; restrict it via role allowlists. Redirects are disabled (v0.1.x).
1111

1212
## Categories
1313
- `transport`

docs/src/content/docs/reference/packets/custom.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,74 @@ Type system: `PacketType::Custom { type_id }`
1111

1212
Runtime: `Packet::Custom(Arc<CustomPacketData>)`
1313

14+
## Why `Custom` exists
15+
`Custom` is StreamKit's **extensibility escape hatch**: it lets plugins and pipelines exchange
16+
structured data **without adding new built-in packet variants**.
17+
18+
It was designed to:
19+
20+
- Keep the core packet set small and stable (important for UIs and SDKs).
21+
- Enable fast iteration for plugin-defined events and typed messages.
22+
- Preserve type-checking via `type_id` so pipelines still validate before running.
23+
- Stay user-friendly over JSON APIs (`encoding: "json"` is debuggable and easy to inspect).
24+
25+
## When to use it
26+
Use `Custom` when you need **structured, typed messages** that don't fit existing packet types, for example:
27+
28+
- Plugin-defined events (e.g. VAD, moderation, scene triggers, rich status updates).
29+
- Application-level envelopes (e.g. tool results, routing hints, structured logs).
30+
- Telemetry-like events (see below) that you want to treat as first-class data.
31+
32+
Prefer other packet types when they fit:
33+
34+
- Audio frames/streams: `/reference/packets/raw-audio/` or `/reference/packets/opus-audio/`
35+
- Plain strings: `/reference/packets/text/`
36+
- Opaque bytes, blobs, or media: `/reference/packets/binary/`
37+
- Speech-to-text results: `/reference/packets/transcription/`
38+
39+
## Type IDs, versioning, and compatibility
40+
`type_id` is the **routing key** for `Custom` and is part of the type system.
41+
42+
- Compatibility: `PacketType::Custom { type_id: "a@1" }` only connects to the same `type_id`.
43+
If you truly want "any custom", use `PacketType::Any` on the input pin.
44+
- Versioning: include a major version suffix like `@1` and bump it for breaking payload changes.
45+
- Namespacing: use a stable, collision-resistant prefix (examples below).
46+
47+
Examples used in this repo:
48+
49+
- `core::telemetry/event@1` (telemetry envelope used on the WebSocket bus)
50+
- `plugin::native::vad/vad-event@1` (VAD-style events)
51+
52+
## Payload conventions
53+
`data` is schema-less JSON: treat it as **untrusted input** and validate it in consumers.
54+
55+
For "event"-shaped payloads, a common convention is an `event_type` string inside `data`:
56+
57+
```json
58+
{
59+
"type_id": "core::telemetry/event@1",
60+
"encoding": "json",
61+
"data": { "event_type": "vad.start", "source": "mic" },
62+
"metadata": { "timestamp_us": 1735257600000000 }
63+
}
64+
```
65+
66+
Related docs:
67+
68+
- WebSocket telemetry events: `/reference/websocket-api/#telemetry-events-nodetelemetry`
69+
- Nodes that observe/emit telemetry: `/reference/nodes/core-telemetry-tap/`, `/reference/nodes/core-telemetry-out/`
70+
71+
## When a core packet type is a better fit
72+
`Custom` is great for iteration, but adding a new core packet type can be worth it when:
73+
74+
- The payload is **high-volume / performance-sensitive** (zero-copy, binary codecs, large frames).
75+
- The payload needs **canonical semantics** across the ecosystem (multiple nodes, UIs, SDKs).
76+
- There are **well-defined fields** that benefit from first-class schema/compat rules (not just `type_id`).
77+
- The payload should be **universally inspectable/renderable** in the UI (timelines, previews, editors).
78+
79+
In those cases, open a GitHub issue describing the use case and examples (or send a PR). The goal is to keep
80+
the built-in packet set small and stable, and graduate widely useful patterns out of `Custom` when needed.
81+
1482
## UI Metadata
1583
- `label`: `Custom`
1684
- `color`: `#e67e22`

docs/src/content/docs/reference/plugins/plugin-native-helsinki.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Source: `plugins/native/helsinki/target/release/libhelsinki.so`
3232
| `model_dir` | `string` | no | `models/opus-mt-en-es` | Path to model directory containing safetensors and tokenizer files |
3333
| `source_language` | `string enum[en, es]` | no | `en` | Source language code: 'en' (English) or 'es' (Spanish) |
3434
| `target_language` | `string enum[en, es]` | no | `es` | Target language code: 'en' (English) or 'es' (Spanish) |
35+
| `warmup` | `boolean` | no | `false` | If true, run a small warmup translation during initialization to reduce first-request latency |
3536

3637

3738
<details>
@@ -86,6 +87,11 @@ Source: `plugins/native/helsinki/target/release/libhelsinki.so`
8687
"es"
8788
],
8889
"type": "string"
90+
},
91+
"warmup": {
92+
"default": false,
93+
"description": "If true, run a small warmup translation during initialization to reduce first-request latency",
94+
"type": "boolean"
8995
}
9096
},
9197
"type": "object"

docs/src/content/docs/reference/plugins/plugin-native-nllb.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ Source: `plugins/native/nllb/target/release/libnllb.so`
3636

3737
## Example Pipeline
3838

39-
> [!CAUTION]
40-
> The NLLB model family is licensed **CC-BY-NC-4.0** (non-commercial). Verify the specific model license and your intended use before deploying in production.
41-
4239
```yaml
4340
# SPDX-FileCopyrightText: © 2025 StreamKit Contributors
4441
#
4542
# SPDX-License-Identifier: MPL-2.0
4643

44+
#
45+
# skit:input_asset_tags=speech
46+
4747
name: Speech Translation (English → Spanish)
4848
description: Translates English speech into Spanish speech
4949
mode: oneshot
@@ -74,6 +74,7 @@ steps:
7474
model_path: models/nllb-200-distilled-600M-ct2-int8
7575
source_language: eng_Latn
7676
target_language: spa_Latn
77+
compute_type: int8
7778
beam_size: 1
7879
num_threads: 4
7980

docs/src/content/docs/reference/plugins/plugin-native-sensevoice.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ Source: `plugins/native/sensevoice/target/release/libsensevoice.so`
4040
## Example Pipeline
4141

4242
```yaml
43+
#
44+
# skit:input_asset_tags=speech
45+
4346
name: Speech-to-Text (SenseVoice)
4447
description: Transcribes speech in multiple languages using SenseVoice
4548
mode: oneshot

docs/src/content/docs/reference/plugins/plugin-native-vad.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ Source: `plugins/native/vad/target/release/libvad.so`
4343
#
4444
# SPDX-License-Identifier: MPL-2.0
4545

46+
#
47+
# skit:input_asset_tags=speech
48+
4649
name: Voice Activity Detection
4750
description: Detects voice activity and outputs events as JSON
4851
mode: oneshot

docs/src/content/docs/reference/plugins/plugin-native-whisper.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ Source: `plugins/native/whisper/target/release/libwhisper.so`
4242
## Example Pipeline
4343

4444
```yaml
45+
#
46+
# skit:input_asset_tags=speech
47+
4548
name: Speech-to-Text (Whisper)
4649
description: Transcribes speech to text using Whisper
4750
mode: oneshot

0 commit comments

Comments
 (0)