@ceralive/cerastream 2026.7.6 → 2026.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +3 -3
- package/dist/client.js +39 -42
- package/dist/config.d.ts +1 -1
- package/dist/config.js +8 -10
- package/dist/constants.d.ts +27 -14
- package/dist/constants.js +36 -18
- package/dist/envelope.d.ts +1 -1
- package/dist/envelope.js +4 -4
- package/dist/errors.d.ts +13 -13
- package/dist/errors.js +43 -43
- package/dist/events.d.ts +102 -98
- package/dist/events.js +30 -30
- package/dist/index.d.ts +9 -9
- package/dist/index.js +9 -9
- package/dist/messages.d.ts +105 -103
- package/dist/messages.js +40 -40
- package/dist/paths.d.ts +2 -2
- package/dist/paths.js +9 -11
- package/dist/transport.js +7 -7
- package/dist/types.d.ts +38 -37
- package/dist/types.js +31 -40
- package/package.json +44 -39
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type HelloResult } from
|
|
2
|
-
import { type EventParams } from
|
|
3
|
-
import { type ChangeConfigParams, type ChangeConfigResult, type GetCapabilitiesResult, type ListDevicesParams, type ListDevicesResult, type PreviewSessionParams, type PreviewSessionResult, type ReloadConfigParams, type ReloadConfigResult, type SetBitrateParams, type SetBitrateResult, type StartParams, type StartResult, type StopParams, type StopResult, type SubscribeEventsParams, type SubscribeEventsResult, type SwitchInputParams, type SwitchInputResult } from
|
|
1
|
+
import { type HelloResult } from './envelope.js';
|
|
2
|
+
import { type EventParams } from './events.js';
|
|
3
|
+
import { type ChangeConfigParams, type ChangeConfigResult, type GetCapabilitiesResult, type ListDevicesParams, type ListDevicesResult, type PreviewSessionParams, type PreviewSessionResult, type ReloadConfigParams, type ReloadConfigResult, type SetBitrateParams, type SetBitrateResult, type StartParams, type StartResult, type StopParams, type StopResult, type SubscribeEventsParams, type SubscribeEventsResult, type SwitchInputParams, type SwitchInputResult } from './messages.js';
|
|
4
4
|
/** Options for {@link connect}. All optional — `connect({})` is valid. */
|
|
5
5
|
export interface ConnectOptions {
|
|
6
6
|
/** Control socket path override. Defaults to the resolved /run/cerastream/control.sock. */
|
package/dist/client.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { CerastreamConnectionError, CerastreamRpcError, CerastreamTimeoutError, } from
|
|
5
|
-
import { eventParamsSchema } from
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { LineSocket } from
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { CONTROL_SOCKET_PATH, PROTOCOL_VERSION } from './constants.js';
|
|
3
|
+
import { helloResultSchema, rpcErrorSchema, rpcResponseSchema, } from './envelope.js';
|
|
4
|
+
import { CerastreamConnectionError, CerastreamRpcError, CerastreamTimeoutError, } from './errors.js';
|
|
5
|
+
import { eventParamsSchema } from './events.js';
|
|
6
|
+
import { changeConfigParamsSchema, changeConfigResultSchema, getCapabilitiesResultSchema, requestSchemas, } from './messages.js';
|
|
7
|
+
import { controlSocketPath } from './paths.js';
|
|
8
|
+
import { LineSocket } from './transport.js';
|
|
9
9
|
const DEFAULTS = {
|
|
10
10
|
requestTimeoutMs: 10_000,
|
|
11
11
|
reconnectInitialDelayMs: 200,
|
|
@@ -26,16 +26,13 @@ class ClientImpl {
|
|
|
26
26
|
reconnectInitialDelayMs;
|
|
27
27
|
reconnectMaxDelayMs;
|
|
28
28
|
constructor(options) {
|
|
29
|
-
this.socketPath =
|
|
30
|
-
|
|
31
|
-
this.
|
|
32
|
-
this.requestTimeoutMs =
|
|
33
|
-
options.requestTimeoutMs ?? DEFAULTS.requestTimeoutMs;
|
|
29
|
+
this.socketPath = options.socketPath ?? safeControlSocketPath();
|
|
30
|
+
this.clientName = options.client ?? '@ceralive/cerastream';
|
|
31
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULTS.requestTimeoutMs;
|
|
34
32
|
this.autoReconnect = options.autoReconnect ?? false;
|
|
35
33
|
this.reconnectInitialDelayMs =
|
|
36
34
|
options.reconnectInitialDelayMs ?? DEFAULTS.reconnectInitialDelayMs;
|
|
37
|
-
this.reconnectMaxDelayMs =
|
|
38
|
-
options.reconnectMaxDelayMs ?? DEFAULTS.reconnectMaxDelayMs;
|
|
35
|
+
this.reconnectMaxDelayMs = options.reconnectMaxDelayMs ?? DEFAULTS.reconnectMaxDelayMs;
|
|
39
36
|
}
|
|
40
37
|
async init() {
|
|
41
38
|
await this.openSocket();
|
|
@@ -55,41 +52,41 @@ class ClientImpl {
|
|
|
55
52
|
this.socket = socket;
|
|
56
53
|
}
|
|
57
54
|
async handshake() {
|
|
58
|
-
const raw = await this.rawRequest(
|
|
55
|
+
const raw = await this.rawRequest('hello', {
|
|
59
56
|
protocol: PROTOCOL_VERSION,
|
|
60
57
|
client: this.clientName,
|
|
61
58
|
});
|
|
62
59
|
return helloResultSchema.parse(raw);
|
|
63
60
|
}
|
|
64
61
|
start(params) {
|
|
65
|
-
return this.call(
|
|
62
|
+
return this.call('start', params);
|
|
66
63
|
}
|
|
67
64
|
stop(params) {
|
|
68
|
-
return this.call(
|
|
65
|
+
return this.call('stop', params);
|
|
69
66
|
}
|
|
70
67
|
reloadConfig(params) {
|
|
71
|
-
return this.call(
|
|
68
|
+
return this.call('reload-config', params);
|
|
72
69
|
}
|
|
73
70
|
setBitrate(params) {
|
|
74
|
-
return this.call(
|
|
71
|
+
return this.call('set-bitrate', params);
|
|
75
72
|
}
|
|
76
73
|
switchInput(params) {
|
|
77
|
-
return this.call(
|
|
74
|
+
return this.call('switch-input', params);
|
|
78
75
|
}
|
|
79
76
|
listDevices(params) {
|
|
80
|
-
return this.call(
|
|
77
|
+
return this.call('list-devices', params);
|
|
81
78
|
}
|
|
82
79
|
async getCapabilities() {
|
|
83
|
-
return getCapabilitiesResultSchema.parse(await this.rawRequest(
|
|
80
|
+
return getCapabilitiesResultSchema.parse(await this.rawRequest('get-capabilities', undefined));
|
|
84
81
|
}
|
|
85
82
|
async changeConfig(params) {
|
|
86
|
-
return changeConfigResultSchema.parse(await this.rawRequest(
|
|
83
|
+
return changeConfigResultSchema.parse(await this.rawRequest('change-config', changeConfigParamsSchema.parse(params)));
|
|
87
84
|
}
|
|
88
85
|
previewSession(params) {
|
|
89
|
-
return this.call(
|
|
86
|
+
return this.call('preview-session', params);
|
|
90
87
|
}
|
|
91
88
|
async subscribeEvents(params, handler) {
|
|
92
|
-
const result = await this.call(
|
|
89
|
+
const result = await this.call('subscribe-events', params);
|
|
93
90
|
const sub = {
|
|
94
91
|
result,
|
|
95
92
|
handler,
|
|
@@ -105,7 +102,7 @@ class ClientImpl {
|
|
|
105
102
|
this.intentionalClose = true;
|
|
106
103
|
for (const sub of this.subscriptions)
|
|
107
104
|
sub.close();
|
|
108
|
-
const conn = new CerastreamConnectionError(
|
|
105
|
+
const conn = new CerastreamConnectionError('client closed', undefined, 'closed');
|
|
109
106
|
this.rejectAllPending(conn);
|
|
110
107
|
this.socket?.close();
|
|
111
108
|
this.socket = undefined;
|
|
@@ -121,11 +118,11 @@ class ClientImpl {
|
|
|
121
118
|
rawRequest(method, params) {
|
|
122
119
|
const socket = this.socket;
|
|
123
120
|
if (!socket) {
|
|
124
|
-
return Promise.reject(new CerastreamConnectionError(
|
|
121
|
+
return Promise.reject(new CerastreamConnectionError('control connection is not open', undefined, 'closed'));
|
|
125
122
|
}
|
|
126
123
|
const id = this.nextId++;
|
|
127
124
|
const envelope = {
|
|
128
|
-
jsonrpc:
|
|
125
|
+
jsonrpc: '2.0',
|
|
129
126
|
id,
|
|
130
127
|
method,
|
|
131
128
|
};
|
|
@@ -143,7 +140,7 @@ class ClientImpl {
|
|
|
143
140
|
catch (err) {
|
|
144
141
|
clearTimeout(timer);
|
|
145
142
|
this.pending.delete(id);
|
|
146
|
-
reject(new CerastreamConnectionError(
|
|
143
|
+
reject(new CerastreamConnectionError('failed to write request', err, 'lost'));
|
|
147
144
|
}
|
|
148
145
|
});
|
|
149
146
|
}
|
|
@@ -157,18 +154,18 @@ class ClientImpl {
|
|
|
157
154
|
}
|
|
158
155
|
if (!isObject(msg))
|
|
159
156
|
return;
|
|
160
|
-
if (msg.method ===
|
|
157
|
+
if (msg.method === 'event') {
|
|
161
158
|
this.dispatchEvent(msg.params);
|
|
162
159
|
return;
|
|
163
160
|
}
|
|
164
|
-
if (!(
|
|
161
|
+
if (!('id' in msg))
|
|
165
162
|
return;
|
|
166
163
|
const id = msg.id;
|
|
167
|
-
if (
|
|
164
|
+
if ('error' in msg) {
|
|
168
165
|
this.settleError(msg);
|
|
169
166
|
return;
|
|
170
167
|
}
|
|
171
|
-
if (
|
|
168
|
+
if ('result' in msg && id != null) {
|
|
172
169
|
const pending = this.pending.get(id);
|
|
173
170
|
if (!pending)
|
|
174
171
|
return;
|
|
@@ -210,7 +207,7 @@ class ClientImpl {
|
|
|
210
207
|
this.socket = undefined;
|
|
211
208
|
if (this.intentionalClose)
|
|
212
209
|
return;
|
|
213
|
-
const conn = new CerastreamConnectionError(
|
|
210
|
+
const conn = new CerastreamConnectionError('control connection lost', err, 'lost');
|
|
214
211
|
this.rejectAllPending(conn);
|
|
215
212
|
if (this.autoReconnect)
|
|
216
213
|
void this.reconnectLoop();
|
|
@@ -253,7 +250,7 @@ class ClientImpl {
|
|
|
253
250
|
topics.add(t);
|
|
254
251
|
if (topics.size === 0)
|
|
255
252
|
return;
|
|
256
|
-
await this.rawRequest(
|
|
253
|
+
await this.rawRequest('subscribe-events', { topics: [...topics] });
|
|
257
254
|
}
|
|
258
255
|
}
|
|
259
256
|
function safeControlSocketPath() {
|
|
@@ -265,7 +262,7 @@ function safeControlSocketPath() {
|
|
|
265
262
|
}
|
|
266
263
|
}
|
|
267
264
|
function isObject(value) {
|
|
268
|
-
return typeof value ===
|
|
265
|
+
return typeof value === 'object' && value !== null;
|
|
269
266
|
}
|
|
270
267
|
// Classify a connect-time transport failure into a stable machine code. Bun's
|
|
271
268
|
// `connect` collapses several distinct errors onto ENOENT and does not reliably
|
|
@@ -275,11 +272,11 @@ function isObject(value) {
|
|
|
275
272
|
// won't accept is `refused` (a crashed/stale listener).
|
|
276
273
|
function classifyConnectError(err, socketPath) {
|
|
277
274
|
const raw = isObject(err) ? err.code : undefined;
|
|
278
|
-
if (raw ===
|
|
279
|
-
return
|
|
280
|
-
if (raw ===
|
|
281
|
-
return
|
|
282
|
-
return existsSync(socketPath) ?
|
|
275
|
+
if (raw === 'ECONNREFUSED')
|
|
276
|
+
return 'refused';
|
|
277
|
+
if (raw === 'EACCES' || raw === 'EPERM')
|
|
278
|
+
return 'unreachable';
|
|
279
|
+
return existsSync(socketPath) ? 'refused' : 'absent';
|
|
283
280
|
}
|
|
284
281
|
function sleep(ms) {
|
|
285
282
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CerastreamConfig, type PartialCerastreamConfig } from
|
|
1
|
+
import { type CerastreamConfig, type PartialCerastreamConfig } from './types.js';
|
|
2
2
|
/** Default on-device config path (systemd `StateDirectory=cerastream`). */
|
|
3
3
|
export declare const DEFAULT_CONFIG_PATH = "/var/lib/cerastream/config.json";
|
|
4
4
|
/** Validate and pretty-print a config to its canonical JSON form. */
|
package/dist/config.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync } from
|
|
2
|
-
import { DEFAULT_BALANCER, DEFAULT_MAX_BITRATE, DEFAULT_MIN_BITRATE, DEFAULT_SRT_LATENCY, } from
|
|
3
|
-
import { cerastreamConfigSchema, } from
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { DEFAULT_BALANCER, DEFAULT_MAX_BITRATE, DEFAULT_MIN_BITRATE, DEFAULT_SRT_LATENCY, } from './constants.js';
|
|
3
|
+
import { cerastreamConfigSchema, } from './types.js';
|
|
4
4
|
// Persisted-config helpers. The unified engine config IS the `start` params
|
|
5
5
|
// (types.cerastreamConfigSchema), so a config written here is exactly what
|
|
6
6
|
// `client.start()` accepts — wire shape and stored profile cannot drift.
|
|
7
7
|
/** Default on-device config path (systemd `StateDirectory=cerastream`). */
|
|
8
|
-
export const DEFAULT_CONFIG_PATH =
|
|
8
|
+
export const DEFAULT_CONFIG_PATH = '/var/lib/cerastream/config.json';
|
|
9
9
|
/** Validate and pretty-print a config to its canonical JSON form. */
|
|
10
10
|
export function serializeCerastreamConfig(config) {
|
|
11
11
|
const parsed = cerastreamConfigSchema.parse(config);
|
|
@@ -18,7 +18,7 @@ export function writeCerastreamConfig(config, path = DEFAULT_CONFIG_PATH) {
|
|
|
18
18
|
}
|
|
19
19
|
/** Read + validate a config from disk. Throws on a missing file or bad shape. */
|
|
20
20
|
export function readCerastreamConfig(path = DEFAULT_CONFIG_PATH) {
|
|
21
|
-
return cerastreamConfigSchema.parse(JSON.parse(readFileSync(path,
|
|
21
|
+
return cerastreamConfigSchema.parse(JSON.parse(readFileSync(path, 'utf8')));
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* Coerce a loose/legacy config object into a valid {@link CerastreamConfig},
|
|
@@ -27,8 +27,8 @@ export function readCerastreamConfig(path = DEFAULT_CONFIG_PATH) {
|
|
|
27
27
|
* required `pipeline` + `srt.host`/`srt.port` cannot be recovered.
|
|
28
28
|
*/
|
|
29
29
|
export function migrateCerastreamConfig(input) {
|
|
30
|
-
if (typeof input !==
|
|
31
|
-
throw new TypeError(
|
|
30
|
+
if (typeof input !== 'object' || input === null) {
|
|
31
|
+
throw new TypeError('migrateCerastreamConfig: expected a config object');
|
|
32
32
|
}
|
|
33
33
|
const raw = input;
|
|
34
34
|
const srt = asRecord(raw.srt);
|
|
@@ -48,7 +48,5 @@ export function migrateCerastreamConfig(input) {
|
|
|
48
48
|
return cerastreamConfigSchema.parse(candidate);
|
|
49
49
|
}
|
|
50
50
|
function asRecord(value) {
|
|
51
|
-
return typeof value ===
|
|
52
|
-
? value
|
|
53
|
-
: {};
|
|
51
|
+
return typeof value === 'object' && value !== null ? value : {};
|
|
54
52
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** JSON-RPC handshake protocol major. Bumped only on a breaking schema change. */
|
|
2
|
-
export declare const PROTOCOL_VERSION:
|
|
2
|
+
export declare const PROTOCOL_VERSION: 'cerastream-ipc/1';
|
|
3
3
|
/**
|
|
4
4
|
* Wire-schema contract version, pinned cross-language with the Rust engine
|
|
5
5
|
* (`crates/cerastream-ipc/src/constants.rs`) and the conformance fixtures. It
|
|
@@ -8,19 +8,19 @@ export declare const PROTOCOL_VERSION: "cerastream-ipc/1";
|
|
|
8
8
|
* additive-only within protocol major `cerastream-ipc/1` (ADR-0002 §4); this value
|
|
9
9
|
* only moves when the wire schema itself does, in lockstep across both languages.
|
|
10
10
|
*/
|
|
11
|
-
export declare const SCHEMA_VERSION:
|
|
11
|
+
export declare const SCHEMA_VERSION: '0.11.0';
|
|
12
12
|
/** Runtime dir holding both control + preview sockets. systemd `RuntimeDirectory=cerastream`. */
|
|
13
|
-
export declare const DEFAULT_IPC_DIR:
|
|
13
|
+
export declare const DEFAULT_IPC_DIR: '/run/cerastream';
|
|
14
14
|
/** Env override for the IPC dir (tests/dev). Defaults to {@link DEFAULT_IPC_DIR}. */
|
|
15
|
-
export declare const IPC_DIR_ENV:
|
|
15
|
+
export declare const IPC_DIR_ENV: 'CERASTREAM_IPC_DIR';
|
|
16
16
|
/** Control-plane socket basename (JSON-RPC 2.0 / NDJSON). */
|
|
17
|
-
export declare const CONTROL_SOCKET_NAME:
|
|
17
|
+
export declare const CONTROL_SOCKET_NAME: 'control.sock';
|
|
18
18
|
/** Preview socket basename (length-prefixed binary frames). */
|
|
19
|
-
export declare const PREVIEW_SOCKET_NAME:
|
|
19
|
+
export declare const PREVIEW_SOCKET_NAME: 'preview.sock';
|
|
20
20
|
/** Default control-plane socket path. */
|
|
21
|
-
export declare const CONTROL_SOCKET_PATH:
|
|
21
|
+
export declare const CONTROL_SOCKET_PATH: '/run/cerastream/control.sock';
|
|
22
22
|
/** Default binary preview socket path. */
|
|
23
|
-
export declare const PREVIEW_SOCKET_PATH:
|
|
23
|
+
export declare const PREVIEW_SOCKET_PATH: '/run/cerastream/preview.sock';
|
|
24
24
|
/** Per-line framing cap (ADR-0002 §1): an oversized line is a fatal protocol error. */
|
|
25
25
|
export declare const MAX_LINE_BYTES: number;
|
|
26
26
|
/** Upper bound (ms) for `reload-config.audio.delay_ms`. Mirrors the Rust `AUDIO_DELAY_MAX_MS` and CeraUI's `AUDIO_DELAY_MAX`. */
|
|
@@ -42,31 +42,44 @@ export declare const LATENCY_MAX_MS = 5000;
|
|
|
42
42
|
* applies it to `SRTO_PACKETFILTER` ONLY against a known FEC-capable receiver.
|
|
43
43
|
* Mirrors the Rust `DEFAULT_FEC_CONFIG`.
|
|
44
44
|
*/
|
|
45
|
-
export declare const DEFAULT_FEC_CONFIG:
|
|
45
|
+
export declare const DEFAULT_FEC_CONFIG: 'fec,layout:staircase,rows:10,cols:10,arq:onreq';
|
|
46
46
|
/**
|
|
47
47
|
* The v1 SRT receive-profile catalog: the preset ids `get-capabilities`
|
|
48
48
|
* advertises in `supported_profiles`. A profile is a named preset CeraUI expands
|
|
49
49
|
* to an SRT/bitrate config; the resolver and the Stream Tuning card read this list
|
|
50
50
|
* to gate which presets the device offers. Mirrors the Rust `SUPPORTED_PROFILES`.
|
|
51
51
|
*/
|
|
52
|
-
export declare const SUPPORTED_PROFILES: readonly [
|
|
52
|
+
export declare const SUPPORTED_PROFILES: readonly ['balanced', 'low-latency', 'resilient', 'classic', 'low-latency-fec'];
|
|
53
53
|
/**
|
|
54
54
|
* Version of the profile catalog {@link SUPPORTED_PROFILES} comes from (semver),
|
|
55
55
|
* echoed by `get-capabilities` as `profile_catalog_version`. Bumped when the preset
|
|
56
56
|
* set or any preset's meaning changes. Mirrors the Rust `PROFILE_CATALOG_VERSION`.
|
|
57
57
|
*/
|
|
58
|
-
export declare const PROFILE_CATALOG_VERSION:
|
|
58
|
+
export declare const PROFILE_CATALOG_VERSION: '1.0.0';
|
|
59
|
+
/**
|
|
60
|
+
* PipeWire-backed audio capture: the engine addresses capture nodes by
|
|
61
|
+
* `node.name`/`object.serial`, so a source with no ALSA card — a Bluetooth
|
|
62
|
+
* microphone is the first one — is selectable as an ordinary node. Unlike the
|
|
63
|
+
* other tokens this one describes the engine's RUNNING configuration, so an
|
|
64
|
+
* engine configured for ALSA omits it even though this catalog lists it. Mirrors
|
|
65
|
+
* the Rust `PIPEWIRE_CAPTURE_FEATURE`.
|
|
66
|
+
*/
|
|
67
|
+
export declare const PIPEWIRE_CAPTURE_FEATURE: 'pipewire-capture';
|
|
59
68
|
/**
|
|
60
69
|
* Named engine features `get-capabilities` advertises in `features`. This is the
|
|
61
70
|
* fail-closed negotiation contract: CeraUI sends a new out-of-schema field ONLY
|
|
62
71
|
* when its feature is listed, so an engine that predates a feature (and silently
|
|
63
72
|
* ignores the field) never applies a semantic the caller assumed. Mirrors the
|
|
64
73
|
* Rust `ENGINE_FEATURES`.
|
|
74
|
+
*
|
|
75
|
+
* This is the full CATALOG. Gate on the token in the engine's own `features`
|
|
76
|
+
* array, never on membership here — a configuration-dependent token is filtered
|
|
77
|
+
* out of the response the engine actually sends.
|
|
65
78
|
*/
|
|
66
|
-
export declare const ENGINE_FEATURES: readonly [
|
|
79
|
+
export declare const ENGINE_FEATURES: readonly ['video-passthrough', 'input-mode', 'audio-pcm-spec', "pipewire-capture"];
|
|
67
80
|
/** Engine binary name (systemd-owned; CeraUI never spawns it — ADR-0005). */
|
|
68
|
-
export declare const CERASTREAM_BIN:
|
|
81
|
+
export declare const CERASTREAM_BIN: 'cerastream';
|
|
69
82
|
export declare const DEFAULT_MIN_BITRATE = 300;
|
|
70
83
|
export declare const DEFAULT_MAX_BITRATE = 6000;
|
|
71
84
|
export declare const DEFAULT_SRT_LATENCY = 2000;
|
|
72
|
-
export declare const DEFAULT_BALANCER:
|
|
85
|
+
export declare const DEFAULT_BALANCER: 'adaptive';
|
package/dist/constants.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// These are CONTRACT values (ADR-0002 / schema.md), not implementation logic —
|
|
3
3
|
// they are the stable wire/runtime literals every consumer derives from.
|
|
4
4
|
/** JSON-RPC handshake protocol major. Bumped only on a breaking schema change. */
|
|
5
|
-
export const PROTOCOL_VERSION =
|
|
5
|
+
export const PROTOCOL_VERSION = 'cerastream-ipc/1';
|
|
6
6
|
/**
|
|
7
7
|
* Wire-schema contract version, pinned cross-language with the Rust engine
|
|
8
8
|
* (`crates/cerastream-ipc/src/constants.rs`) and the conformance fixtures. It
|
|
@@ -11,19 +11,19 @@ export const PROTOCOL_VERSION = "cerastream-ipc/1";
|
|
|
11
11
|
* additive-only within protocol major `cerastream-ipc/1` (ADR-0002 §4); this value
|
|
12
12
|
* only moves when the wire schema itself does, in lockstep across both languages.
|
|
13
13
|
*/
|
|
14
|
-
export const SCHEMA_VERSION =
|
|
14
|
+
export const SCHEMA_VERSION = '0.11.0';
|
|
15
15
|
/** Runtime dir holding both control + preview sockets. systemd `RuntimeDirectory=cerastream`. */
|
|
16
|
-
export const DEFAULT_IPC_DIR =
|
|
16
|
+
export const DEFAULT_IPC_DIR = '/run/cerastream';
|
|
17
17
|
/** Env override for the IPC dir (tests/dev). Defaults to {@link DEFAULT_IPC_DIR}. */
|
|
18
|
-
export const IPC_DIR_ENV =
|
|
18
|
+
export const IPC_DIR_ENV = 'CERASTREAM_IPC_DIR';
|
|
19
19
|
/** Control-plane socket basename (JSON-RPC 2.0 / NDJSON). */
|
|
20
|
-
export const CONTROL_SOCKET_NAME =
|
|
20
|
+
export const CONTROL_SOCKET_NAME = 'control.sock';
|
|
21
21
|
/** Preview socket basename (length-prefixed binary frames). */
|
|
22
|
-
export const PREVIEW_SOCKET_NAME =
|
|
22
|
+
export const PREVIEW_SOCKET_NAME = 'preview.sock';
|
|
23
23
|
/** Default control-plane socket path. */
|
|
24
|
-
export const CONTROL_SOCKET_PATH =
|
|
24
|
+
export const CONTROL_SOCKET_PATH = '/run/cerastream/control.sock';
|
|
25
25
|
/** Default binary preview socket path. */
|
|
26
|
-
export const PREVIEW_SOCKET_PATH =
|
|
26
|
+
export const PREVIEW_SOCKET_PATH = '/run/cerastream/preview.sock';
|
|
27
27
|
/** Per-line framing cap (ADR-0002 §1): an oversized line is a fatal protocol error. */
|
|
28
28
|
export const MAX_LINE_BYTES = 1024 * 1024; // 1 MiB
|
|
29
29
|
/** Upper bound (ms) for `reload-config.audio.delay_ms`. Mirrors the Rust `AUDIO_DELAY_MAX_MS` and CeraUI's `AUDIO_DELAY_MAX`. */
|
|
@@ -45,7 +45,7 @@ export const LATENCY_MAX_MS = 5000;
|
|
|
45
45
|
* applies it to `SRTO_PACKETFILTER` ONLY against a known FEC-capable receiver.
|
|
46
46
|
* Mirrors the Rust `DEFAULT_FEC_CONFIG`.
|
|
47
47
|
*/
|
|
48
|
-
export const DEFAULT_FEC_CONFIG =
|
|
48
|
+
export const DEFAULT_FEC_CONFIG = 'fec,layout:staircase,rows:10,cols:10,arq:onreq';
|
|
49
49
|
/**
|
|
50
50
|
* The v1 SRT receive-profile catalog: the preset ids `get-capabilities`
|
|
51
51
|
* advertises in `supported_profiles`. A profile is a named preset CeraUI expands
|
|
@@ -53,30 +53,48 @@ export const DEFAULT_FEC_CONFIG = "fec,layout:staircase,rows:10,cols:10,arq:onre
|
|
|
53
53
|
* to gate which presets the device offers. Mirrors the Rust `SUPPORTED_PROFILES`.
|
|
54
54
|
*/
|
|
55
55
|
export const SUPPORTED_PROFILES = [
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
'balanced',
|
|
57
|
+
'low-latency',
|
|
58
|
+
'resilient',
|
|
59
|
+
'classic',
|
|
60
|
+
'low-latency-fec',
|
|
61
61
|
];
|
|
62
62
|
/**
|
|
63
63
|
* Version of the profile catalog {@link SUPPORTED_PROFILES} comes from (semver),
|
|
64
64
|
* echoed by `get-capabilities` as `profile_catalog_version`. Bumped when the preset
|
|
65
65
|
* set or any preset's meaning changes. Mirrors the Rust `PROFILE_CATALOG_VERSION`.
|
|
66
66
|
*/
|
|
67
|
-
export const PROFILE_CATALOG_VERSION =
|
|
67
|
+
export const PROFILE_CATALOG_VERSION = '1.0.0';
|
|
68
|
+
/**
|
|
69
|
+
* PipeWire-backed audio capture: the engine addresses capture nodes by
|
|
70
|
+
* `node.name`/`object.serial`, so a source with no ALSA card — a Bluetooth
|
|
71
|
+
* microphone is the first one — is selectable as an ordinary node. Unlike the
|
|
72
|
+
* other tokens this one describes the engine's RUNNING configuration, so an
|
|
73
|
+
* engine configured for ALSA omits it even though this catalog lists it. Mirrors
|
|
74
|
+
* the Rust `PIPEWIRE_CAPTURE_FEATURE`.
|
|
75
|
+
*/
|
|
76
|
+
export const PIPEWIRE_CAPTURE_FEATURE = 'pipewire-capture';
|
|
68
77
|
/**
|
|
69
78
|
* Named engine features `get-capabilities` advertises in `features`. This is the
|
|
70
79
|
* fail-closed negotiation contract: CeraUI sends a new out-of-schema field ONLY
|
|
71
80
|
* when its feature is listed, so an engine that predates a feature (and silently
|
|
72
81
|
* ignores the field) never applies a semantic the caller assumed. Mirrors the
|
|
73
82
|
* Rust `ENGINE_FEATURES`.
|
|
83
|
+
*
|
|
84
|
+
* This is the full CATALOG. Gate on the token in the engine's own `features`
|
|
85
|
+
* array, never on membership here — a configuration-dependent token is filtered
|
|
86
|
+
* out of the response the engine actually sends.
|
|
74
87
|
*/
|
|
75
|
-
export const ENGINE_FEATURES = [
|
|
88
|
+
export const ENGINE_FEATURES = [
|
|
89
|
+
'video-passthrough',
|
|
90
|
+
'input-mode',
|
|
91
|
+
'audio-pcm-spec',
|
|
92
|
+
PIPEWIRE_CAPTURE_FEATURE,
|
|
93
|
+
];
|
|
76
94
|
/** Engine binary name (systemd-owned; CeraUI never spawns it — ADR-0005). */
|
|
77
|
-
export const CERASTREAM_BIN =
|
|
95
|
+
export const CERASTREAM_BIN = 'cerastream';
|
|
78
96
|
// ---- config defaults (mirror ceracoder, the engine being replaced) ----
|
|
79
97
|
export const DEFAULT_MIN_BITRATE = 300; // kbps
|
|
80
98
|
export const DEFAULT_MAX_BITRATE = 6000; // kbps
|
|
81
99
|
export const DEFAULT_SRT_LATENCY = 2000; // ms
|
|
82
|
-
export const DEFAULT_BALANCER =
|
|
100
|
+
export const DEFAULT_BALANCER = 'adaptive';
|
package/dist/envelope.d.ts
CHANGED
package/dist/envelope.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { z } from
|
|
2
|
-
import { PROTOCOL_VERSION } from
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PROTOCOL_VERSION } from './constants.js';
|
|
3
3
|
// JSON-RPC 2.0 envelope, newline-delimited over the control UDS (ADR-0002 §2,
|
|
4
4
|
// schema.md "Envelope"). The JSON shape on the wire is the contract — not any
|
|
5
5
|
// Rust serde type.
|
|
6
|
-
export const jsonrpcVersion = z.literal(
|
|
6
|
+
export const jsonrpcVersion = z.literal('2.0');
|
|
7
7
|
export const requestId = z.union([z.number().int(), z.string()]);
|
|
8
8
|
// ---- request: client → server ----
|
|
9
9
|
export const rpcRequestSchema = z.object({
|
|
@@ -32,7 +32,7 @@ export const rpcErrorSchema = z.object({
|
|
|
32
32
|
// ---- event: server → client, no id ----
|
|
33
33
|
export const rpcEventSchema = z.object({
|
|
34
34
|
jsonrpc: jsonrpcVersion,
|
|
35
|
-
method: z.literal(
|
|
35
|
+
method: z.literal('event'),
|
|
36
36
|
params: z
|
|
37
37
|
.object({
|
|
38
38
|
type: z.string(), // event type (see events.ts)
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { z } from
|
|
1
|
+
import { z } from 'zod';
|
|
2
2
|
/**
|
|
3
3
|
* Thrown by every contract-stub function body (Task 17). The schema in this
|
|
4
4
|
* package is real and frozen; the IPC client/transport is implemented in Task 31.
|
|
@@ -43,7 +43,7 @@ export declare class CerastreamRpcError extends Error {
|
|
|
43
43
|
* - `closed` — the client was closed, or a request was issued on a
|
|
44
44
|
* not-open connection.
|
|
45
45
|
*/
|
|
46
|
-
export declare const CERASTREAM_CONNECT_ERROR_CODES: readonly [
|
|
46
|
+
export declare const CERASTREAM_CONNECT_ERROR_CODES: readonly ['absent', 'refused', 'unreachable', 'lost', 'closed'];
|
|
47
47
|
export type CerastreamConnectErrorCode = (typeof CERASTREAM_CONNECT_ERROR_CODES)[number];
|
|
48
48
|
/**
|
|
49
49
|
* Thrown when the control connection is lost (socket closed/errored) while a
|
|
@@ -63,15 +63,15 @@ export declare class CerastreamTimeoutError extends Error {
|
|
|
63
63
|
constructor(method: string, timeoutMs: number);
|
|
64
64
|
}
|
|
65
65
|
export declare const rpcErrorCodeSchema: z.ZodEnum<{
|
|
66
|
-
"cerastream.protocol.unsupported_version": "cerastream.protocol.unsupported_version";
|
|
67
|
-
"cerastream.params.invalid": "cerastream.params.invalid";
|
|
68
|
-
"cerastream.state.not_streaming": "cerastream.state.not_streaming";
|
|
69
|
-
"cerastream.state.already_streaming": "cerastream.state.already_streaming";
|
|
70
|
-
"cerastream.device.not_found": "cerastream.device.not_found";
|
|
71
66
|
"cerastream.audio.device_not_found": "cerastream.audio.device_not_found";
|
|
72
67
|
"cerastream.bitrate.out_of_range": "cerastream.bitrate.out_of_range";
|
|
73
|
-
"cerastream.
|
|
68
|
+
"cerastream.device.not_found": "cerastream.device.not_found";
|
|
74
69
|
"cerastream.internal": "cerastream.internal";
|
|
70
|
+
"cerastream.params.invalid": "cerastream.params.invalid";
|
|
71
|
+
"cerastream.preview.unsupported_tier": "cerastream.preview.unsupported_tier";
|
|
72
|
+
"cerastream.protocol.unsupported_version": "cerastream.protocol.unsupported_version";
|
|
73
|
+
"cerastream.state.already_streaming": "cerastream.state.already_streaming";
|
|
74
|
+
"cerastream.state.not_streaming": "cerastream.state.not_streaming";
|
|
75
75
|
}>;
|
|
76
76
|
export type RpcErrorCode = z.infer<typeof rpcErrorCodeSchema>;
|
|
77
77
|
/**
|
|
@@ -81,14 +81,14 @@ export type RpcErrorCode = z.infer<typeof rpcErrorCodeSchema>;
|
|
|
81
81
|
*/
|
|
82
82
|
export declare const RPC_ERROR_NUMERIC: Readonly<Record<RpcErrorCode, number>>;
|
|
83
83
|
export declare const processErrorCodeSchema: z.ZodEnum<{
|
|
84
|
-
srtla_initial_connect_failed: "srtla_initial_connect_failed";
|
|
85
|
-
srtla_no_connections: "srtla_no_connections";
|
|
86
84
|
capture_audio_error: "capture_audio_error";
|
|
85
|
+
capture_unrecoverable: "capture_unrecoverable";
|
|
87
86
|
capture_video_error: "capture_video_error";
|
|
88
87
|
pipeline_stall: "pipeline_stall";
|
|
89
88
|
srt_connect_failed: "srt_connect_failed";
|
|
90
89
|
srt_connection_lost: "srt_connection_lost";
|
|
91
|
-
|
|
90
|
+
srtla_initial_connect_failed: "srtla_initial_connect_failed";
|
|
91
|
+
srtla_no_connections: "srtla_no_connections";
|
|
92
92
|
}>;
|
|
93
93
|
export type ProcessErrorCode = z.infer<typeof processErrorCodeSchema>;
|
|
94
94
|
/**
|
|
@@ -97,15 +97,15 @@ export type ProcessErrorCode = z.infer<typeof processErrorCodeSchema>;
|
|
|
97
97
|
*/
|
|
98
98
|
export declare const captureUnrecoverableReasonSchema: z.ZodEnum<{
|
|
99
99
|
node_absent_reprobe_disabled: "node_absent_reprobe_disabled";
|
|
100
|
-
reprobe_no_reenumeration: "reprobe_no_reenumeration";
|
|
101
100
|
reprobe_identity_changed: "reprobe_identity_changed";
|
|
101
|
+
reprobe_no_reenumeration: "reprobe_no_reenumeration";
|
|
102
102
|
reprobe_node_still_absent: "reprobe_node_still_absent";
|
|
103
103
|
reprobe_unavailable: "reprobe_unavailable";
|
|
104
104
|
}>;
|
|
105
105
|
export type CaptureUnrecoverableReason = z.infer<typeof captureUnrecoverableReasonSchema>;
|
|
106
106
|
/** Origin of a Tier 2 runtime error (the notification channel CeraUI routes on). */
|
|
107
107
|
export declare const processErrorSourceSchema: z.ZodEnum<{
|
|
108
|
-
srtla: "srtla";
|
|
109
108
|
engine: "engine";
|
|
109
|
+
srtla: "srtla";
|
|
110
110
|
}>;
|
|
111
111
|
export type ProcessErrorSource = z.infer<typeof processErrorSourceSchema>;
|