@camstack/types 1.1.47 → 1.1.49
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/addon.js +2 -2
- package/dist/addon.mjs +2 -2
- package/dist/capabilities/index.d.ts +3 -1
- package/dist/capabilities/pipeline-analytics.cap.d.ts +6 -0
- package/dist/capabilities/recording-export.cap.d.ts +305 -0
- package/dist/capabilities/recording.cap.d.ts +21 -0
- package/dist/capabilities/zone-rules.cap.d.ts +27 -3
- package/dist/enums/event-category.d.ts +24 -0
- package/dist/enums.js +1 -1
- package/dist/enums.mjs +1 -1
- package/dist/{event-category-AkBNxg_X.js → event-category-CGj9fI4L.js} +24 -0
- package/dist/{event-category-H4AVePnn.mjs → event-category-D4HJq7Mw.mjs} +24 -0
- package/dist/generated/addon-api.d.ts +418 -8
- package/dist/generated/capability-router-map.d.ts +5 -2
- package/dist/generated/device-proxy.d.ts +2 -0
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +2 -0
- package/dist/index.js +299 -10
- package/dist/index.mjs +287 -11
- package/dist/interfaces/event-bus.d.ts +44 -0
- package/dist/interfaces/readiness.d.ts +8 -5
- package/dist/interfaces/recording-config.d.ts +54 -0
- package/dist/readiness/readiness-registry.d.ts +33 -10
- package/dist/{sleep-BkhAiFKX.js → sleep-BfvNtyu8.js} +71 -16
- package/dist/{sleep-CK899CTS.mjs → sleep-DOq2moJx.mjs} +71 -16
- package/package.json +1 -1
|
@@ -98,19 +98,42 @@ export declare class ReadinessRegistry implements IReadinessRegistry {
|
|
|
98
98
|
*/
|
|
99
99
|
getSnapshotForTransport(): readonly ReadinessRecord[];
|
|
100
100
|
/**
|
|
101
|
-
* Hydrate the snapshot from an authoritative source
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
101
|
+
* Hydrate the snapshot from an authoritative source — a RECONCILE, not
|
|
102
|
+
* an add-only merge (D8: readiness events are telemetry and may be
|
|
103
|
+
* lost; the on-reconnect/periodic snapshot re-pull is the repair path,
|
|
104
|
+
* so it MUST be able to advance a stale record — the 2026-07-17
|
|
105
|
+
* "still awaiting platform-probe forever" wedge was this method
|
|
106
|
+
* skipping every already-seen key).
|
|
107
107
|
*
|
|
108
|
-
*
|
|
109
|
-
* derived from
|
|
110
|
-
*
|
|
111
|
-
*
|
|
108
|
+
* - **Unseen keys** are added (epoch 1 — mirrors the value the
|
|
109
|
+
* consumer would have derived from the first observed `ready`).
|
|
110
|
+
* - **Existing keys** are UPDATED when the authoritative record
|
|
111
|
+
* carries a different generation (producer restart / synthetic-down
|
|
112
|
+
* superseded — epoch bumps on a new-generation `ready`, mirroring
|
|
113
|
+
* `ingest`), or a FORWARD state move within the same generation
|
|
114
|
+
* (`starting → ready → down`; within one producer generation a
|
|
115
|
+
* snapshot can only be ahead of a lost delta, never behind it).
|
|
116
|
+
* - **Never a same-generation regress** — a snapshot pulled just
|
|
117
|
+
* before a live delta landed must not un-ready a record (the next
|
|
118
|
+
* reconcile round converges it anyway).
|
|
119
|
+
* - **Never a record this process is authoritative for** — node-scoped
|
|
120
|
+
* records for our own nodeId, and device/global records we emitted,
|
|
121
|
+
* keep local truth (an authority's stale copy of OUR record must
|
|
122
|
+
* not regress us).
|
|
123
|
+
*
|
|
124
|
+
* Every applied entry dispatches a one-shot transition to matching
|
|
125
|
+
* subscriptions so pending `awaitReady` callers unblock without having
|
|
126
|
+
* to wait for a fresh event.
|
|
112
127
|
*/
|
|
113
128
|
hydrate(records: readonly ReadinessRecord[]): void;
|
|
129
|
+
/**
|
|
130
|
+
* True when THIS process is the origin authority for `record` — a
|
|
131
|
+
* snapshot pulled from elsewhere must never overwrite it:
|
|
132
|
+
* - node-scoped records whose `scope.nodeId` is our own node id
|
|
133
|
+
* (this process — or a child bridged onto our bus — emits them);
|
|
134
|
+
* - device/global-scoped records whose latest transition WE emitted.
|
|
135
|
+
*/
|
|
136
|
+
private isLocallyAuthoritative;
|
|
114
137
|
/** Shallow copy of the full snapshot — mainly for diagnostics/tests. */
|
|
115
138
|
getAll(): ReadonlyMap<string, ReadinessRecord>;
|
|
116
139
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_event_category = require("./event-category-
|
|
1
|
+
const require_event_category = require("./event-category-CGj9fI4L.js");
|
|
2
2
|
let zod = require("zod");
|
|
3
3
|
//#region src/disposer-chain.ts
|
|
4
4
|
var DisposerChain = class {
|
|
@@ -1487,6 +1487,19 @@ function scopeKey(scope) {
|
|
|
1487
1487
|
case "device": return `device:${scope.deviceId}`;
|
|
1488
1488
|
}
|
|
1489
1489
|
}
|
|
1490
|
+
/**
|
|
1491
|
+
* Producer transition order within ONE generation: `starting → ready →
|
|
1492
|
+
* down`. Used by `hydrate` to accept only forward moves for
|
|
1493
|
+
* same-generation snapshot records (a snapshot can be ahead of a lost
|
|
1494
|
+
* delta, never behind it, within one producer generation).
|
|
1495
|
+
*/
|
|
1496
|
+
function stateRank(state) {
|
|
1497
|
+
switch (state) {
|
|
1498
|
+
case "starting": return 0;
|
|
1499
|
+
case "ready": return 1;
|
|
1500
|
+
case "down": return 2;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1490
1503
|
function scopesEqual(a, b) {
|
|
1491
1504
|
if (a.type !== b.type) return false;
|
|
1492
1505
|
if (a.type === "global" || b.type === "global") return true;
|
|
@@ -1537,43 +1550,70 @@ var ReadinessRegistry = class {
|
|
|
1537
1550
|
return Array.from(this.snapshot.values());
|
|
1538
1551
|
}
|
|
1539
1552
|
/**
|
|
1540
|
-
* Hydrate the snapshot from an authoritative source
|
|
1541
|
-
*
|
|
1542
|
-
*
|
|
1543
|
-
*
|
|
1544
|
-
*
|
|
1545
|
-
*
|
|
1553
|
+
* Hydrate the snapshot from an authoritative source — a RECONCILE, not
|
|
1554
|
+
* an add-only merge (D8: readiness events are telemetry and may be
|
|
1555
|
+
* lost; the on-reconnect/periodic snapshot re-pull is the repair path,
|
|
1556
|
+
* so it MUST be able to advance a stale record — the 2026-07-17
|
|
1557
|
+
* "still awaiting platform-probe forever" wedge was this method
|
|
1558
|
+
* skipping every already-seen key).
|
|
1559
|
+
*
|
|
1560
|
+
* - **Unseen keys** are added (epoch 1 — mirrors the value the
|
|
1561
|
+
* consumer would have derived from the first observed `ready`).
|
|
1562
|
+
* - **Existing keys** are UPDATED when the authoritative record
|
|
1563
|
+
* carries a different generation (producer restart / synthetic-down
|
|
1564
|
+
* superseded — epoch bumps on a new-generation `ready`, mirroring
|
|
1565
|
+
* `ingest`), or a FORWARD state move within the same generation
|
|
1566
|
+
* (`starting → ready → down`; within one producer generation a
|
|
1567
|
+
* snapshot can only be ahead of a lost delta, never behind it).
|
|
1568
|
+
* - **Never a same-generation regress** — a snapshot pulled just
|
|
1569
|
+
* before a live delta landed must not un-ready a record (the next
|
|
1570
|
+
* reconcile round converges it anyway).
|
|
1571
|
+
* - **Never a record this process is authoritative for** — node-scoped
|
|
1572
|
+
* records for our own nodeId, and device/global records we emitted,
|
|
1573
|
+
* keep local truth (an authority's stale copy of OUR record must
|
|
1574
|
+
* not regress us).
|
|
1546
1575
|
*
|
|
1547
|
-
*
|
|
1548
|
-
*
|
|
1549
|
-
*
|
|
1550
|
-
* first `ready` event directly.
|
|
1576
|
+
* Every applied entry dispatches a one-shot transition to matching
|
|
1577
|
+
* subscriptions so pending `awaitReady` callers unblock without having
|
|
1578
|
+
* to wait for a fresh event.
|
|
1551
1579
|
*/
|
|
1552
1580
|
hydrate(records) {
|
|
1553
1581
|
const now = this.now();
|
|
1554
1582
|
for (const record of records) {
|
|
1555
1583
|
const key = readinessKey(record.capName, record.scope);
|
|
1556
|
-
|
|
1584
|
+
const prev = this.snapshot.get(key) ?? null;
|
|
1585
|
+
let epoch;
|
|
1586
|
+
let durationInPrevState;
|
|
1587
|
+
if (prev !== null) {
|
|
1588
|
+
if (this.isLocallyAuthoritative(prev)) continue;
|
|
1589
|
+
const sameGeneration = prev.generation === record.generation;
|
|
1590
|
+
if (sameGeneration && stateRank(record.state) <= stateRank(prev.state)) continue;
|
|
1591
|
+
epoch = !sameGeneration && record.state === "ready" ? prev.epoch + 1 : prev.epoch;
|
|
1592
|
+
durationInPrevState = Math.max(0, now - prev.lastChange);
|
|
1593
|
+
} else {
|
|
1594
|
+
epoch = 1;
|
|
1595
|
+
durationInPrevState = 0;
|
|
1596
|
+
}
|
|
1557
1597
|
const hydrated = {
|
|
1558
1598
|
capName: record.capName,
|
|
1559
1599
|
scope: record.scope,
|
|
1560
1600
|
state: record.state,
|
|
1561
1601
|
generation: record.generation,
|
|
1562
|
-
epoch
|
|
1602
|
+
epoch,
|
|
1563
1603
|
lastChange: now,
|
|
1564
1604
|
sourceNodeId: record.sourceNodeId
|
|
1565
1605
|
};
|
|
1566
1606
|
this.snapshot.set(key, hydrated);
|
|
1567
|
-
if (this.logger) this.logger.debug(`readiness: ${record.capName} (${scopeKey(record.scope)}) → ${record.state} (hydrated, gen=${record.generation.slice(0, 6)})`);
|
|
1607
|
+
if (this.logger) this.logger.debug(`readiness: ${record.capName} (${scopeKey(record.scope)}) → ${record.state} (hydrated${prev !== null ? " update" : ""}, gen=${record.generation.slice(0, 6)})`);
|
|
1568
1608
|
const transition = {
|
|
1569
1609
|
capName: record.capName,
|
|
1570
1610
|
scope: record.scope,
|
|
1571
1611
|
state: record.state,
|
|
1572
|
-
epoch
|
|
1612
|
+
epoch,
|
|
1573
1613
|
generation: record.generation,
|
|
1574
1614
|
sourceNodeId: "hydrated",
|
|
1575
1615
|
ts: now,
|
|
1576
|
-
durationInPrevState
|
|
1616
|
+
durationInPrevState
|
|
1577
1617
|
};
|
|
1578
1618
|
for (const sub of this.subscriptions) {
|
|
1579
1619
|
if (sub.capName !== record.capName) continue;
|
|
@@ -1586,6 +1626,17 @@ var ReadinessRegistry = class {
|
|
|
1586
1626
|
}
|
|
1587
1627
|
}
|
|
1588
1628
|
}
|
|
1629
|
+
/**
|
|
1630
|
+
* True when THIS process is the origin authority for `record` — a
|
|
1631
|
+
* snapshot pulled from elsewhere must never overwrite it:
|
|
1632
|
+
* - node-scoped records whose `scope.nodeId` is our own node id
|
|
1633
|
+
* (this process — or a child bridged onto our bus — emits them);
|
|
1634
|
+
* - device/global-scoped records whose latest transition WE emitted.
|
|
1635
|
+
*/
|
|
1636
|
+
isLocallyAuthoritative(record) {
|
|
1637
|
+
if (record.scope.type === "node") return record.scope.nodeId === this.sourceNodeId;
|
|
1638
|
+
return record.sourceNodeId === this.sourceNodeId;
|
|
1639
|
+
}
|
|
1589
1640
|
/** Shallow copy of the full snapshot — mainly for diagnostics/tests. */
|
|
1590
1641
|
getAll() {
|
|
1591
1642
|
return new Map(this.snapshot);
|
|
@@ -3175,6 +3226,10 @@ function createDeviceProxy(api, binding, opts) {
|
|
|
3175
3226
|
getDeviceLiveContribution: (input) => dispatchSystem("recording", "getDeviceLiveContribution", "query", input),
|
|
3176
3227
|
applyDeviceSettingsPatch: (input) => dispatchSystem("recording", "applyDeviceSettingsPatch", "mutation", input)
|
|
3177
3228
|
},
|
|
3229
|
+
recordingExport: {
|
|
3230
|
+
createExport: (input) => dispatchSystem("recordingExport", "createExport", "mutation", input),
|
|
3231
|
+
listExports: (input) => dispatchSystem("recordingExport", "listExports", "query", input)
|
|
3232
|
+
},
|
|
3178
3233
|
streamBroker: {
|
|
3179
3234
|
publishCameraStream: (input) => dispatchSystem("streamBroker", "publishCameraStream", "mutation", input),
|
|
3180
3235
|
retractCameraStream: (input) => dispatchSystem("streamBroker", "retractCameraStream", "mutation", input),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as EventCategory } from "./event-category-
|
|
1
|
+
import { t as EventCategory } from "./event-category-D4HJq7Mw.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
//#region src/disposer-chain.ts
|
|
4
4
|
var DisposerChain = class {
|
|
@@ -1487,6 +1487,19 @@ function scopeKey(scope) {
|
|
|
1487
1487
|
case "device": return `device:${scope.deviceId}`;
|
|
1488
1488
|
}
|
|
1489
1489
|
}
|
|
1490
|
+
/**
|
|
1491
|
+
* Producer transition order within ONE generation: `starting → ready →
|
|
1492
|
+
* down`. Used by `hydrate` to accept only forward moves for
|
|
1493
|
+
* same-generation snapshot records (a snapshot can be ahead of a lost
|
|
1494
|
+
* delta, never behind it, within one producer generation).
|
|
1495
|
+
*/
|
|
1496
|
+
function stateRank(state) {
|
|
1497
|
+
switch (state) {
|
|
1498
|
+
case "starting": return 0;
|
|
1499
|
+
case "ready": return 1;
|
|
1500
|
+
case "down": return 2;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1490
1503
|
function scopesEqual(a, b) {
|
|
1491
1504
|
if (a.type !== b.type) return false;
|
|
1492
1505
|
if (a.type === "global" || b.type === "global") return true;
|
|
@@ -1537,43 +1550,70 @@ var ReadinessRegistry = class {
|
|
|
1537
1550
|
return Array.from(this.snapshot.values());
|
|
1538
1551
|
}
|
|
1539
1552
|
/**
|
|
1540
|
-
* Hydrate the snapshot from an authoritative source
|
|
1541
|
-
*
|
|
1542
|
-
*
|
|
1543
|
-
*
|
|
1544
|
-
*
|
|
1545
|
-
*
|
|
1553
|
+
* Hydrate the snapshot from an authoritative source — a RECONCILE, not
|
|
1554
|
+
* an add-only merge (D8: readiness events are telemetry and may be
|
|
1555
|
+
* lost; the on-reconnect/periodic snapshot re-pull is the repair path,
|
|
1556
|
+
* so it MUST be able to advance a stale record — the 2026-07-17
|
|
1557
|
+
* "still awaiting platform-probe forever" wedge was this method
|
|
1558
|
+
* skipping every already-seen key).
|
|
1559
|
+
*
|
|
1560
|
+
* - **Unseen keys** are added (epoch 1 — mirrors the value the
|
|
1561
|
+
* consumer would have derived from the first observed `ready`).
|
|
1562
|
+
* - **Existing keys** are UPDATED when the authoritative record
|
|
1563
|
+
* carries a different generation (producer restart / synthetic-down
|
|
1564
|
+
* superseded — epoch bumps on a new-generation `ready`, mirroring
|
|
1565
|
+
* `ingest`), or a FORWARD state move within the same generation
|
|
1566
|
+
* (`starting → ready → down`; within one producer generation a
|
|
1567
|
+
* snapshot can only be ahead of a lost delta, never behind it).
|
|
1568
|
+
* - **Never a same-generation regress** — a snapshot pulled just
|
|
1569
|
+
* before a live delta landed must not un-ready a record (the next
|
|
1570
|
+
* reconcile round converges it anyway).
|
|
1571
|
+
* - **Never a record this process is authoritative for** — node-scoped
|
|
1572
|
+
* records for our own nodeId, and device/global records we emitted,
|
|
1573
|
+
* keep local truth (an authority's stale copy of OUR record must
|
|
1574
|
+
* not regress us).
|
|
1546
1575
|
*
|
|
1547
|
-
*
|
|
1548
|
-
*
|
|
1549
|
-
*
|
|
1550
|
-
* first `ready` event directly.
|
|
1576
|
+
* Every applied entry dispatches a one-shot transition to matching
|
|
1577
|
+
* subscriptions so pending `awaitReady` callers unblock without having
|
|
1578
|
+
* to wait for a fresh event.
|
|
1551
1579
|
*/
|
|
1552
1580
|
hydrate(records) {
|
|
1553
1581
|
const now = this.now();
|
|
1554
1582
|
for (const record of records) {
|
|
1555
1583
|
const key = readinessKey(record.capName, record.scope);
|
|
1556
|
-
|
|
1584
|
+
const prev = this.snapshot.get(key) ?? null;
|
|
1585
|
+
let epoch;
|
|
1586
|
+
let durationInPrevState;
|
|
1587
|
+
if (prev !== null) {
|
|
1588
|
+
if (this.isLocallyAuthoritative(prev)) continue;
|
|
1589
|
+
const sameGeneration = prev.generation === record.generation;
|
|
1590
|
+
if (sameGeneration && stateRank(record.state) <= stateRank(prev.state)) continue;
|
|
1591
|
+
epoch = !sameGeneration && record.state === "ready" ? prev.epoch + 1 : prev.epoch;
|
|
1592
|
+
durationInPrevState = Math.max(0, now - prev.lastChange);
|
|
1593
|
+
} else {
|
|
1594
|
+
epoch = 1;
|
|
1595
|
+
durationInPrevState = 0;
|
|
1596
|
+
}
|
|
1557
1597
|
const hydrated = {
|
|
1558
1598
|
capName: record.capName,
|
|
1559
1599
|
scope: record.scope,
|
|
1560
1600
|
state: record.state,
|
|
1561
1601
|
generation: record.generation,
|
|
1562
|
-
epoch
|
|
1602
|
+
epoch,
|
|
1563
1603
|
lastChange: now,
|
|
1564
1604
|
sourceNodeId: record.sourceNodeId
|
|
1565
1605
|
};
|
|
1566
1606
|
this.snapshot.set(key, hydrated);
|
|
1567
|
-
if (this.logger) this.logger.debug(`readiness: ${record.capName} (${scopeKey(record.scope)}) → ${record.state} (hydrated, gen=${record.generation.slice(0, 6)})`);
|
|
1607
|
+
if (this.logger) this.logger.debug(`readiness: ${record.capName} (${scopeKey(record.scope)}) → ${record.state} (hydrated${prev !== null ? " update" : ""}, gen=${record.generation.slice(0, 6)})`);
|
|
1568
1608
|
const transition = {
|
|
1569
1609
|
capName: record.capName,
|
|
1570
1610
|
scope: record.scope,
|
|
1571
1611
|
state: record.state,
|
|
1572
|
-
epoch
|
|
1612
|
+
epoch,
|
|
1573
1613
|
generation: record.generation,
|
|
1574
1614
|
sourceNodeId: "hydrated",
|
|
1575
1615
|
ts: now,
|
|
1576
|
-
durationInPrevState
|
|
1616
|
+
durationInPrevState
|
|
1577
1617
|
};
|
|
1578
1618
|
for (const sub of this.subscriptions) {
|
|
1579
1619
|
if (sub.capName !== record.capName) continue;
|
|
@@ -1586,6 +1626,17 @@ var ReadinessRegistry = class {
|
|
|
1586
1626
|
}
|
|
1587
1627
|
}
|
|
1588
1628
|
}
|
|
1629
|
+
/**
|
|
1630
|
+
* True when THIS process is the origin authority for `record` — a
|
|
1631
|
+
* snapshot pulled from elsewhere must never overwrite it:
|
|
1632
|
+
* - node-scoped records whose `scope.nodeId` is our own node id
|
|
1633
|
+
* (this process — or a child bridged onto our bus — emits them);
|
|
1634
|
+
* - device/global-scoped records whose latest transition WE emitted.
|
|
1635
|
+
*/
|
|
1636
|
+
isLocallyAuthoritative(record) {
|
|
1637
|
+
if (record.scope.type === "node") return record.scope.nodeId === this.sourceNodeId;
|
|
1638
|
+
return record.sourceNodeId === this.sourceNodeId;
|
|
1639
|
+
}
|
|
1589
1640
|
/** Shallow copy of the full snapshot — mainly for diagnostics/tests. */
|
|
1590
1641
|
getAll() {
|
|
1591
1642
|
return new Map(this.snapshot);
|
|
@@ -3175,6 +3226,10 @@ function createDeviceProxy(api, binding, opts) {
|
|
|
3175
3226
|
getDeviceLiveContribution: (input) => dispatchSystem("recording", "getDeviceLiveContribution", "query", input),
|
|
3176
3227
|
applyDeviceSettingsPatch: (input) => dispatchSystem("recording", "applyDeviceSettingsPatch", "mutation", input)
|
|
3177
3228
|
},
|
|
3229
|
+
recordingExport: {
|
|
3230
|
+
createExport: (input) => dispatchSystem("recordingExport", "createExport", "mutation", input),
|
|
3231
|
+
listExports: (input) => dispatchSystem("recordingExport", "listExports", "query", input)
|
|
3232
|
+
},
|
|
3178
3233
|
streamBroker: {
|
|
3179
3234
|
publishCameraStream: (input) => dispatchSystem("streamBroker", "publishCameraStream", "mutation", input),
|
|
3180
3235
|
retractCameraStream: (input) => dispatchSystem("streamBroker", "retractCameraStream", "mutation", input),
|