@camstack/addon-export-alexa 1.2.134 → 1.2.135
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/export-alexa.addon.js +81 -480
- package/dist/export-alexa.addon.mjs +81 -480
- package/lambda-template/README.md +49 -21
- package/lambda-template/aws.js +32 -16
- package/lambda-template/broker.js +3 -3
- package/lambda-template/debug-trace.js +100 -0
- package/lambda-template/index.js +19 -8
- package/lambda-template/secrets.js +24 -21
- package/package.json +1 -1
|
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
//#endregion
|
|
27
27
|
let node_crypto = require("node:crypto");
|
|
28
28
|
node_crypto = __toESM(node_crypto, 1);
|
|
29
|
-
//#region ../types/dist/event-category-
|
|
29
|
+
//#region ../types/dist/event-category-B_0XEcLF.mjs
|
|
30
30
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
31
31
|
EventCategory["SystemBoot"] = "system.boot";
|
|
32
32
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -527,15 +527,6 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
527
527
|
EventCategory["AgentWsDisconnected"] = "agent.ws.disconnected";
|
|
528
528
|
EventCategory["AgentBackupActivated"] = "agent.backup.activated";
|
|
529
529
|
EventCategory["OrchestrationSettingsUpdated"] = "orchestration.settings-updated";
|
|
530
|
-
/**
|
|
531
|
-
* Per-agent hwaccel preference changed (user override set, cleared, or
|
|
532
|
-
* re-probed). Observability event — decoders pull the current pref at
|
|
533
|
-
* `createSession`, so running sessions keep their current backend until
|
|
534
|
-
* they rotate naturally (camera add/remove, stream restart). Future
|
|
535
|
-
* work can wire a listener in stream-broker that force-rotates live
|
|
536
|
-
* sessions; for now this event powers logs + admin-UI toast feedback.
|
|
537
|
-
*/
|
|
538
|
-
EventCategory["PipelineAgentHwaccelChanged"] = "pipeline.agent-hwaccel-changed";
|
|
539
530
|
EventCategory["MotionAnalysis"] = "detection.motion-analysis";
|
|
540
531
|
/** All raw motion zones from CCL before minArea filter — for UI debug overlay. */
|
|
541
532
|
EventCategory["MotionZonesRaw"] = "detection.motion-zones-raw";
|
|
@@ -5406,7 +5397,7 @@ var ZodIssueCode = {
|
|
|
5406
5397
|
var ZodFirstPartyTypeKind;
|
|
5407
5398
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5408
5399
|
//#endregion
|
|
5409
|
-
//#region ../types/dist/sleep-
|
|
5400
|
+
//#region ../types/dist/sleep-BNeXenvr.mjs
|
|
5410
5401
|
/**
|
|
5411
5402
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5412
5403
|
* window to float samples (D455).
|
|
@@ -6772,32 +6763,12 @@ object({
|
|
|
6772
6763
|
audioCodec: string().optional(),
|
|
6773
6764
|
metadata: record(string(), unknown()).readonly().optional()
|
|
6774
6765
|
});
|
|
6775
|
-
var EncodedPacketSchema = object({
|
|
6776
|
-
type: _enum(["video", "audio"]),
|
|
6777
|
-
data: _instanceof(Uint8Array),
|
|
6778
|
-
pts: number(),
|
|
6779
|
-
dts: number(),
|
|
6780
|
-
keyframe: boolean(),
|
|
6781
|
-
codec: string()
|
|
6782
|
-
});
|
|
6783
|
-
var DecodedFrameSchema = object({
|
|
6784
|
-
data: _instanceof(Uint8Array),
|
|
6785
|
-
width: number(),
|
|
6786
|
-
height: number(),
|
|
6787
|
-
format: _enum([
|
|
6788
|
-
"jpeg",
|
|
6789
|
-
"rgb",
|
|
6790
|
-
"bgr",
|
|
6791
|
-
"yuv420",
|
|
6792
|
-
"gray"
|
|
6793
|
-
]),
|
|
6794
|
-
timestamp: number()
|
|
6795
|
-
});
|
|
6796
6766
|
/**
|
|
6797
6767
|
* Wire schema for `FrameHandle` — a zero-pixel, serialisable reference to a
|
|
6798
6768
|
* frame in a shared-memory ring (Phase 5 / D9). Mirrors the `FrameHandle` TS
|
|
6799
|
-
* interface in `interfaces/frame-handle.ts` field-for-field so a
|
|
6800
|
-
*
|
|
6769
|
+
* interface in `interfaces/frame-handle.ts` field-for-field so a cap method
|
|
6770
|
+
* (the runner's native-crop and pipeline-executor inputs) can carry handles
|
|
6771
|
+
* over tRPC / Moleculer.
|
|
6801
6772
|
*
|
|
6802
6773
|
* The `satisfies` assertion below pins this schema to the interface: if a
|
|
6803
6774
|
* field is added to / removed from `FrameHandle` without a matching schema
|
|
@@ -6823,50 +6794,6 @@ var FrameHandleSchema = object({
|
|
|
6823
6794
|
slotCount: number().int().positive()
|
|
6824
6795
|
});
|
|
6825
6796
|
/**
|
|
6826
|
-
* Pixel format a frame-handle subscriber can request from the broker
|
|
6827
|
-
* (Phase 5 / D9). The packed, raster subset of `FrameFormat` — the formats a
|
|
6828
|
-
* `frameSink: 'shm'` decoder session can write into a `FrameRing` slot.
|
|
6829
|
-
* `jpeg` is excluded: a variable-length stream is not a fixed-stride ring
|
|
6830
|
-
* payload, and no decoded-frame consumer requests it over the shm plane.
|
|
6831
|
-
*/
|
|
6832
|
-
var FrameHandleFormatSchema = _enum([
|
|
6833
|
-
"rgb",
|
|
6834
|
-
"bgr",
|
|
6835
|
-
"yuv420",
|
|
6836
|
-
"gray"
|
|
6837
|
-
]);
|
|
6838
|
-
/**
|
|
6839
|
-
* Input for `stream-broker.subscribeFrames` (Phase 5 / D9). A consumer asks the
|
|
6840
|
-
* broker for a `FrameHandle` stream of one `format`; the broker maintains one
|
|
6841
|
-
* shared-memory ring per `(brokerId, format)` actually requested, so a `gray`
|
|
6842
|
-
* subscriber (motion) and an `rgb` subscriber (detection) each read the format
|
|
6843
|
-
* they asked for with no broker-side conversion.
|
|
6844
|
-
*/
|
|
6845
|
-
var SubscribeFramesInputSchema = object({
|
|
6846
|
-
brokerId: string(),
|
|
6847
|
-
format: FrameHandleFormatSchema,
|
|
6848
|
-
/**
|
|
6849
|
-
* Optional reader-side cadence hint in frames per second. The broker does
|
|
6850
|
-
* NOT throttle — latest-wins ring reads drop frames implicitly for a slow
|
|
6851
|
-
* consumer. The value is echoed back in `SubscribeFramesResult.maxFps` so
|
|
6852
|
-
* the consumer can pace its own `pullFrameHandles` polling.
|
|
6853
|
-
*/
|
|
6854
|
-
maxFps: number().positive().optional(),
|
|
6855
|
-
/** Short caller-identity tag (`motion`, `detection`, …) for diagnostics. */
|
|
6856
|
-
tag: string().optional()
|
|
6857
|
-
});
|
|
6858
|
-
/**
|
|
6859
|
-
* Result of `stream-broker.subscribeFrames`. The consumer then polls
|
|
6860
|
-
* `pullFrameHandles({ subscriptionId, maxCount })` and feeds each returned
|
|
6861
|
-
* `FrameHandle` to a `FrameRingReader`.
|
|
6862
|
-
*/
|
|
6863
|
-
var SubscribeFramesResultSchema = object({
|
|
6864
|
-
/** Opaque id the consumer passes to `pullFrameHandles` / `unsubscribeFrames`. */
|
|
6865
|
-
subscriptionId: string(),
|
|
6866
|
-
/** Reader-side cadence hint (frames/s) — echoes `SubscribeFramesInput.maxFps`. */
|
|
6867
|
-
maxFps: number().nonnegative()
|
|
6868
|
-
});
|
|
6869
|
-
/**
|
|
6870
6797
|
* Wire schema for a decoded audio chunk (Phase 5 / D9). Mirrors the
|
|
6871
6798
|
* `DecodedAudioChunk` TS interface in `interfaces/stream-broker.ts`: PCM
|
|
6872
6799
|
* sample bytes plus the track parameters a consumer needs to interpret them.
|
|
@@ -6874,8 +6801,8 @@ var SubscribeFramesResultSchema = object({
|
|
|
6874
6801
|
* Audio chunks are tiny (a ~500ms AudioCodecSession window is a few KB of
|
|
6875
6802
|
* Float32 PCM), so unlike video frames they ship their bytes INLINE over
|
|
6876
6803
|
* tRPC / Moleculer — no shared-memory plane. `data` is typed `Uint8Array`
|
|
6877
|
-
* (the wire-serialisable supertype of `Buffer`)
|
|
6878
|
-
*
|
|
6804
|
+
* (the wire-serialisable supertype of `Buffer`); a `Buffer` is assignable to
|
|
6805
|
+
* it.
|
|
6879
6806
|
*/
|
|
6880
6807
|
var AudioChunkFormatSchema = _enum(AUDIO_CHUNK_FORMATS);
|
|
6881
6808
|
var DecodedAudioChunkSchema = object({
|
|
@@ -6893,11 +6820,10 @@ var DecodedAudioChunkSchema = object({
|
|
|
6893
6820
|
format: AudioChunkFormatSchema.optional()
|
|
6894
6821
|
});
|
|
6895
6822
|
/**
|
|
6896
|
-
* Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9).
|
|
6897
|
-
*
|
|
6898
|
-
*
|
|
6899
|
-
*
|
|
6900
|
-
* `pullAudioChunks`.
|
|
6823
|
+
* Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9). Audio ships
|
|
6824
|
+
* its bytes inline: a consumer asks the broker for the decoded audio-chunk
|
|
6825
|
+
* stream of one broker; the broker keeps a per-subscription bounded FIFO queue
|
|
6826
|
+
* the consumer drains via `pullAudioChunks`.
|
|
6901
6827
|
*/
|
|
6902
6828
|
var SubscribeAudioChunksInputSchema = object({
|
|
6903
6829
|
brokerId: string(),
|
|
@@ -6928,9 +6854,7 @@ var BrokerStatsSchema = object({
|
|
|
6928
6854
|
"stopped"
|
|
6929
6855
|
]),
|
|
6930
6856
|
inputFps: number(),
|
|
6931
|
-
decodeFps: number(),
|
|
6932
6857
|
encodedSubscribers: number(),
|
|
6933
|
-
decodedSubscribers: number(),
|
|
6934
6858
|
uptimeMs: number(),
|
|
6935
6859
|
bitrateKbps: number(),
|
|
6936
6860
|
idrIntervalMs: number(),
|
|
@@ -6943,14 +6867,6 @@ var BrokerStatsSchema = object({
|
|
|
6943
6867
|
preBufferMs: number(),
|
|
6944
6868
|
preBufferPackets: number(),
|
|
6945
6869
|
/**
|
|
6946
|
-
* Moleculer node id of the decoder provider currently servicing this
|
|
6947
|
-
* stream's decoded subscribers. `null` until the deferred decoder is
|
|
6948
|
-
* created (no decoded clients yet, or codec not detected). Surfaces the
|
|
6949
|
-
* runtime decoder placement so the UI can show "Decoder: <agent>" without
|
|
6950
|
-
* a separate cap call per broker.
|
|
6951
|
-
*/
|
|
6952
|
-
decoderNodeId: string().nullable(),
|
|
6953
|
-
/**
|
|
6954
6870
|
* Detected audio track parameters from the RTSP DESCRIBE / SDP. `null`
|
|
6955
6871
|
* when the stream has no audio track or the broker is in cold start.
|
|
6956
6872
|
* `supported = false` means the codec was detected but the local
|
|
@@ -10473,70 +10389,6 @@ var StorageLocationDeclarationSchema = object({
|
|
|
10473
10389
|
"backup"
|
|
10474
10390
|
]).optional()
|
|
10475
10391
|
});
|
|
10476
|
-
var DecoderStatsSchema = object({
|
|
10477
|
-
inputFps: number(),
|
|
10478
|
-
outputFps: number(),
|
|
10479
|
-
avgDecodeTimeMs: number(),
|
|
10480
|
-
droppedFrames: number(),
|
|
10481
|
-
/**
|
|
10482
|
-
* Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
|
|
10483
|
-
* lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
|
|
10484
|
-
* the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
|
|
10485
|
-
* is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
|
|
10486
|
-
*/
|
|
10487
|
-
lagMs: number().optional(),
|
|
10488
|
-
effectiveFps: number().optional(),
|
|
10489
|
-
adaptiveFps: number().optional()
|
|
10490
|
-
});
|
|
10491
|
-
var DecoderSessionConfigSchema = object({
|
|
10492
|
-
codec: string(),
|
|
10493
|
-
maxFps: number().default(0),
|
|
10494
|
-
outputFormat: _enum([
|
|
10495
|
-
"jpeg",
|
|
10496
|
-
"rgb",
|
|
10497
|
-
"bgr",
|
|
10498
|
-
"yuv420",
|
|
10499
|
-
"gray"
|
|
10500
|
-
]).default("jpeg"),
|
|
10501
|
-
scale: number().default(1),
|
|
10502
|
-
width: number().optional(),
|
|
10503
|
-
height: number().optional(),
|
|
10504
|
-
/**
|
|
10505
|
-
* Identifier of the camera this decoder session serves. Optional
|
|
10506
|
-
* because the cap is generic (any caller could request decode), but
|
|
10507
|
-
* stream-broker passes it so decoder logs include `deviceId` for
|
|
10508
|
-
* per-camera filtering when diagnosing failures (e.g. node-av
|
|
10509
|
-
* sendPacket errors on a single hung camera).
|
|
10510
|
-
*/
|
|
10511
|
-
deviceId: number().int().nonnegative().optional(),
|
|
10512
|
-
/**
|
|
10513
|
-
* Free-form tag for log scoping. Stream-broker uses
|
|
10514
|
-
* `broker:<deviceId>/<profile>`. Decoder session logger surfaces it
|
|
10515
|
-
* on every line so `grep tag=broker:5/high` filters one camera
|
|
10516
|
-
* profile cleanly.
|
|
10517
|
-
*/
|
|
10518
|
-
tag: string().optional(),
|
|
10519
|
-
/**
|
|
10520
|
-
* Where the session delivers decoded frames (Phase 5 / D9):
|
|
10521
|
-
*
|
|
10522
|
-
* - `'callback'` (default) — the legacy pixel path: decoded frames are
|
|
10523
|
-
* buffered as `DecodedFrame`s and drained via `pullFrames`.
|
|
10524
|
-
* - `'shm'` — the shared-memory frame plane: decoded frames are written
|
|
10525
|
-
* into an OS shared-memory ring and drained as zero-pixel
|
|
10526
|
-
* `FrameHandle`s via `pullHandles`. A session is one mode or the
|
|
10527
|
-
* other — `pullFrames` returns nothing for an `'shm'` session and
|
|
10528
|
-
* `pullHandles` returns nothing for a `'callback'` session.
|
|
10529
|
-
*/
|
|
10530
|
-
frameSink: _enum(["callback", "shm"]).default("callback"),
|
|
10531
|
-
/**
|
|
10532
|
-
* Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
|
|
10533
|
-
* a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
|
|
10534
|
-
* real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
|
|
10535
|
-
* stream-broker's `streamingDebug` gate — off by default so production logs
|
|
10536
|
-
* stay quiet and the emit path pays zero per-frame cost when disabled.
|
|
10537
|
-
*/
|
|
10538
|
-
debug: boolean().optional()
|
|
10539
|
-
});
|
|
10540
10392
|
/**
|
|
10541
10393
|
* Per-component log CHANNELS — the gate a hot path consults, and the registry
|
|
10542
10394
|
* an addon declares its channels in.
|
|
@@ -12797,13 +12649,6 @@ var BrokerRtspClientSchema = object({
|
|
|
12797
12649
|
lastRtpAt: number(),
|
|
12798
12650
|
bytesSent: number()
|
|
12799
12651
|
});
|
|
12800
|
-
var BrokerDecodedClientSchema = object({
|
|
12801
|
-
tag: string(),
|
|
12802
|
-
subscribedAt: number(),
|
|
12803
|
-
maxFps: number(),
|
|
12804
|
-
framesDelivered: number(),
|
|
12805
|
-
framesDropped: number()
|
|
12806
|
-
});
|
|
12807
12652
|
var BrokerAudioClientSchema = object({
|
|
12808
12653
|
tag: string(),
|
|
12809
12654
|
subscribedAt: number(),
|
|
@@ -12895,7 +12740,6 @@ var BrokerEncodedClientSchema = object({
|
|
|
12895
12740
|
});
|
|
12896
12741
|
var BrokerClientsSchema = object({
|
|
12897
12742
|
rtsp: array(BrokerRtspClientSchema).readonly(),
|
|
12898
|
-
decoded: array(BrokerDecodedClientSchema).readonly(),
|
|
12899
12743
|
audio: array(BrokerAudioClientSchema).readonly(),
|
|
12900
12744
|
encoded: array(BrokerEncodedClientSchema).readonly(),
|
|
12901
12745
|
pipeClients: number(),
|
|
@@ -13264,11 +13108,7 @@ method(object({
|
|
|
13264
13108
|
auth: "admin"
|
|
13265
13109
|
}), method(object({ brokerId: string() }), BrokerClientsSchema), method(object({
|
|
13266
13110
|
brokerId: string(),
|
|
13267
|
-
channel: _enum([
|
|
13268
|
-
"rtsp",
|
|
13269
|
-
"decoded",
|
|
13270
|
-
"audio"
|
|
13271
|
-
]),
|
|
13111
|
+
channel: _enum(["rtsp", "audio"]),
|
|
13272
13112
|
handle: string()
|
|
13273
13113
|
}), object({ killed: boolean() }), {
|
|
13274
13114
|
kind: "mutation",
|
|
@@ -13303,10 +13143,7 @@ method(object({
|
|
|
13303
13143
|
}), method(SubscribeAudioChunksInputSchema, SubscribeAudioChunksResultSchema, { kind: "mutation" }), method(object({
|
|
13304
13144
|
subscriptionId: string(),
|
|
13305
13145
|
maxCount: number().int().positive().default(8)
|
|
13306
|
-
}), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(
|
|
13307
|
-
subscriptionId: string(),
|
|
13308
|
-
maxCount: number().int().positive().default(4)
|
|
13309
|
-
}), array(FrameHandleSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
|
|
13146
|
+
}), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
|
|
13310
13147
|
brokerId: string(),
|
|
13311
13148
|
seconds: number().min(0).max(30)
|
|
13312
13149
|
}), _void(), {
|
|
@@ -14463,54 +14300,12 @@ id: union([string(), number()]) }), {
|
|
|
14463
14300
|
kind: "mutation",
|
|
14464
14301
|
auth: "admin"
|
|
14465
14302
|
});
|
|
14466
|
-
|
|
14467
|
-
* shm ring usage stats for a `frameSink: 'shm'` decoder session —
|
|
14468
|
-
* exposed via `decoder.getShmStats` so downstream consumers can
|
|
14469
|
-
* observe ring pressure (slot count, byte budget, hit/miss ratio).
|
|
14470
|
-
*/
|
|
14471
|
-
var ShmRingStatsSchema = object({
|
|
14472
|
-
sessionId: string(),
|
|
14473
|
-
slotCount: number().int(),
|
|
14474
|
-
slotByteLength: number().int(),
|
|
14475
|
-
segmentBytes: number().int(),
|
|
14476
|
-
budgetMb: number().int(),
|
|
14477
|
-
framesWritten: number().int(),
|
|
14478
|
-
getFrameHits: number().int(),
|
|
14479
|
-
getFrameMisses: number().int()
|
|
14480
|
-
});
|
|
14481
|
-
method(object({ codec: string() }), boolean()), method(_void(), object({
|
|
14303
|
+
method(_void(), object({
|
|
14482
14304
|
id: string(),
|
|
14483
14305
|
name: string(),
|
|
14484
|
-
isPullMode: boolean().optional(),
|
|
14485
|
-
priority: number().optional(),
|
|
14486
14306
|
hwaccel: string().optional(),
|
|
14487
14307
|
probedBestHwaccel: string().optional()
|
|
14488
|
-
})), method(
|
|
14489
|
-
sessionId: string(),
|
|
14490
|
-
nodeId: string()
|
|
14491
|
-
})), method(object({ sessionId: string() }), _void()), method(object({
|
|
14492
|
-
sessionId: string(),
|
|
14493
|
-
packet: EncodedPacketSchema
|
|
14494
|
-
}), _void()), method(object({
|
|
14495
|
-
sessionId: string(),
|
|
14496
|
-
url: string()
|
|
14497
|
-
}), _void()), method(object({
|
|
14498
|
-
sessionId: string(),
|
|
14499
|
-
maxCount: number().default(1),
|
|
14500
|
-
waitMs: number().optional()
|
|
14501
|
-
}), array(DecodedFrameSchema)), method(object({
|
|
14502
|
-
sessionId: string(),
|
|
14503
|
-
maxCount: number().default(1),
|
|
14504
|
-
waitMs: number().optional()
|
|
14505
|
-
}), array(FrameHandleSchema)), method(object({ handle: FrameHandleSchema }), DecodedFrameSchema.nullable()), method(object({ sessionId: string() }), ShmRingStatsSchema.nullable()), method(object({
|
|
14506
|
-
sessionId: string(),
|
|
14507
|
-
config: DecoderSessionConfigSchema.partial()
|
|
14508
|
-
}), _void()), method(object({ sessionId: string() }), DecoderStatsSchema), method(_void(), array(object({
|
|
14509
|
-
sessionId: string(),
|
|
14510
|
-
codec: string(),
|
|
14511
|
-
outputFormat: string(),
|
|
14512
|
-
createdAtMs: number()
|
|
14513
|
-
})).readonly()), method(_void(), object({ backend: string() }), {
|
|
14308
|
+
})), method(_void(), object({ backend: string() }), {
|
|
14514
14309
|
kind: "mutation",
|
|
14515
14310
|
auth: "admin"
|
|
14516
14311
|
});
|
|
@@ -21571,8 +21366,8 @@ Object.freeze(Object.fromEntries([{
|
|
|
21571
21366
|
var CLUSTER_STEP_SETTING_FIELDS = [{
|
|
21572
21367
|
stepId: "face-embedding",
|
|
21573
21368
|
key: "minLandmarkFaceSize",
|
|
21574
|
-
label: "Min face size
|
|
21575
|
-
description: "
|
|
21369
|
+
label: "Min face size to embed (detection-frame px)",
|
|
21370
|
+
description: "Faces smaller than this in the small frame the detector sees are not embedded, so they can never be recognised. Below it the face cannot be aligned reliably and a bad embedding matches everyone. Same value on every node. 0 = no limit.",
|
|
21576
21371
|
type: "slider",
|
|
21577
21372
|
min: 0,
|
|
21578
21373
|
max: 64,
|
|
@@ -23624,21 +23419,6 @@ var PipelineDefaultStepSchema = lazy(() => object({
|
|
|
23624
23419
|
group: string().optional(),
|
|
23625
23420
|
settings: record(string(), unknown()).optional()
|
|
23626
23421
|
}));
|
|
23627
|
-
var PipelineTemplateStepSchema = lazy(() => object({
|
|
23628
|
-
addonId: string(),
|
|
23629
|
-
enabled: boolean(),
|
|
23630
|
-
modelId: string(),
|
|
23631
|
-
children: array(PipelineTemplateStepSchema).readonly(),
|
|
23632
|
-
settings: record(string(), unknown()).optional()
|
|
23633
|
-
}));
|
|
23634
|
-
var PipelineTemplateSchema$1 = object({
|
|
23635
|
-
id: string(),
|
|
23636
|
-
name: string(),
|
|
23637
|
-
createdAt: string(),
|
|
23638
|
-
updatedAt: string(),
|
|
23639
|
-
engine: PipelineEngineChoiceSchema,
|
|
23640
|
-
steps: array(PipelineTemplateStepSchema).readonly()
|
|
23641
|
-
});
|
|
23642
23422
|
var PipelineModelOptionSchema = object({
|
|
23643
23423
|
id: string(),
|
|
23644
23424
|
name: string(),
|
|
@@ -23850,15 +23630,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
|
|
|
23850
23630
|
}), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
|
|
23851
23631
|
steps: array(PipelineStepInputSchema),
|
|
23852
23632
|
deviceKey: string().optional()
|
|
23853
|
-
}), PipelineValidationResultSchema), method(_void(),
|
|
23854
|
-
name: string(),
|
|
23855
|
-
steps: array(PipelineTemplateStepSchema).readonly(),
|
|
23856
|
-
engine: PipelineEngineChoiceSchema
|
|
23857
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
|
|
23858
|
-
id: string(),
|
|
23859
|
-
name: string().optional(),
|
|
23860
|
-
steps: array(PipelineTemplateStepSchema).readonly().optional()
|
|
23861
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
23633
|
+
}), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
23862
23634
|
addonId: string(),
|
|
23863
23635
|
modelId: string(),
|
|
23864
23636
|
format: ModelFormatSchema$2
|
|
@@ -25268,14 +25040,15 @@ var RunnerLocalLoadSchema = object({
|
|
|
25268
25040
|
* Per-inference-device live load (multi-device C4). One entry per deviceKey
|
|
25269
25041
|
* this runner currently has attached cameras on, so the orchestrator's second
|
|
25270
25042
|
* `balance()` pass (over a node's devices) weights on real per-pool session
|
|
25271
|
-
* counts. Empty on single-device / pre-multi-device runners.
|
|
25272
|
-
* per
|
|
25043
|
+
* counts. Empty on single-device / pre-multi-device runners. There is no
|
|
25044
|
+
* per-device queue depth: the inference pool's backlog has no accessor, and
|
|
25045
|
+
* a field that always read 0 was removed rather than shown as a measurement
|
|
25046
|
+
* (D762).
|
|
25273
25047
|
*/
|
|
25274
25048
|
devices: array(object({
|
|
25275
25049
|
deviceKey: string(),
|
|
25276
25050
|
backend: string(),
|
|
25277
|
-
attachedCameras: number()
|
|
25278
|
-
queueDepthTotal: number()
|
|
25051
|
+
attachedCameras: number()
|
|
25279
25052
|
})).default([]),
|
|
25280
25053
|
/** Hardware capability flags reported by this node. */
|
|
25281
25054
|
hardware: object({
|
|
@@ -25489,14 +25262,6 @@ var CameraPipelineConfigSchema = object({
|
|
|
25489
25262
|
settings: record(string(), unknown()).readonly().optional()
|
|
25490
25263
|
}).nullable().optional()
|
|
25491
25264
|
});
|
|
25492
|
-
var PipelineTemplateSchema = object({
|
|
25493
|
-
id: string(),
|
|
25494
|
-
name: string(),
|
|
25495
|
-
description: string().optional(),
|
|
25496
|
-
config: CameraPipelineConfigSchema,
|
|
25497
|
-
createdAt: string(),
|
|
25498
|
-
updatedAt: string()
|
|
25499
|
-
});
|
|
25500
25265
|
var DeviceStepConfigSchema = object({
|
|
25501
25266
|
modelId: string().optional(),
|
|
25502
25267
|
settings: record(string(), unknown()).optional(),
|
|
@@ -25606,7 +25371,10 @@ var PipelineAssignmentSchema = object({
|
|
|
25606
25371
|
});
|
|
25607
25372
|
/**
|
|
25608
25373
|
* Per-agent load summary surfaced to the load balancer + dashboards.
|
|
25609
|
-
* Aggregated from each runner's `getLocalLoad` cap call.
|
|
25374
|
+
* Aggregated from each runner's `getLocalLoad` cap call. In the
|
|
25375
|
+
* `getAgentLoad` report, a single-device node's default-pool sessions (no
|
|
25376
|
+
* `deviceKey`) are credited to its one eligible device in `load.devices` —
|
|
25377
|
+
* the default pool IS that device (D745); the balancer's census stays raw.
|
|
25610
25378
|
*/
|
|
25611
25379
|
var AgentLoadSummarySchema = object({
|
|
25612
25380
|
nodeId: string(),
|
|
@@ -25695,26 +25463,27 @@ var CameraBrokerStatusSchema = object({
|
|
|
25695
25463
|
width: number(),
|
|
25696
25464
|
height: number(),
|
|
25697
25465
|
subscribers: number(),
|
|
25698
|
-
|
|
25699
|
-
|
|
25466
|
+
/**
|
|
25467
|
+
* Encoded packets/s the broker receives from the camera. null when the
|
|
25468
|
+
* broker's stats read failed — unknown, never 0 (a 0 here reads as a stall).
|
|
25469
|
+
* There is no output rate: decoding runs in the session decode workers, not
|
|
25470
|
+
* in the broker, so the broker's own decoded-frame rate is 0 on every live
|
|
25471
|
+
* camera and is not served (D758).
|
|
25472
|
+
*/
|
|
25473
|
+
inFps: number().nullable()
|
|
25700
25474
|
})).readonly(),
|
|
25701
25475
|
webrtcSessions: number(),
|
|
25702
25476
|
rtspRestream: boolean()
|
|
25703
25477
|
});
|
|
25704
|
-
/**
|
|
25705
|
-
|
|
25706
|
-
|
|
25707
|
-
|
|
25708
|
-
|
|
25709
|
-
|
|
25710
|
-
|
|
25711
|
-
|
|
25712
|
-
var CameraDecoderStatusSchema = object({
|
|
25713
|
-
nodeId: string(),
|
|
25714
|
-
formats: array(string()).readonly(),
|
|
25715
|
-
sessionCount: number(),
|
|
25716
|
-
shm: CameraDecoderShmSchema
|
|
25717
|
-
});
|
|
25478
|
+
/**
|
|
25479
|
+
* Decoder block — WHERE decode runs (co-located with the detection node by
|
|
25480
|
+
* construction); null when the camera has no detection node. It carries no
|
|
25481
|
+
* frame counter: the shared-memory plane whose counters it used to serve is
|
|
25482
|
+
* gone, and those fields read 0 forever. Whether frames actually flow is read
|
|
25483
|
+
* from `detection.actualFps` (frames delivered to and processed by the
|
|
25484
|
+
* detector), never from a counter nothing feeds.
|
|
25485
|
+
*/
|
|
25486
|
+
var CameraDecoderStatusSchema = object({ nodeId: string() });
|
|
25718
25487
|
/** Motion block — null when motion detection is not active for this device. */
|
|
25719
25488
|
var CameraMotionStatusSchema = object({
|
|
25720
25489
|
enabled: boolean(),
|
|
@@ -26167,25 +25936,7 @@ method(object({
|
|
|
26167
25936
|
}), method(_void(), DiskReconcileJobSchema, {
|
|
26168
25937
|
kind: "mutation",
|
|
26169
25938
|
auth: "admin"
|
|
26170
|
-
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" })
|
|
26171
|
-
name: string(),
|
|
26172
|
-
description: string().optional(),
|
|
26173
|
-
config: CameraPipelineConfigSchema
|
|
26174
|
-
}), PipelineTemplateSchema, {
|
|
26175
|
-
kind: "mutation",
|
|
26176
|
-
auth: "admin"
|
|
26177
|
-
}), method(object({
|
|
26178
|
-
id: string(),
|
|
26179
|
-
name: string().optional(),
|
|
26180
|
-
description: string().optional(),
|
|
26181
|
-
config: CameraPipelineConfigSchema.optional()
|
|
26182
|
-
}), PipelineTemplateSchema, {
|
|
26183
|
-
kind: "mutation",
|
|
26184
|
-
auth: "admin"
|
|
26185
|
-
}), method(object({ id: string() }), object({ success: literal(true) }), {
|
|
26186
|
-
kind: "mutation",
|
|
26187
|
-
auth: "admin"
|
|
26188
|
-
});
|
|
25939
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" });
|
|
26189
25940
|
/**
|
|
26190
25941
|
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
26191
25942
|
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
@@ -28405,8 +28156,6 @@ var WebrtcStreamChoiceSchema = object({
|
|
|
28405
28156
|
]).nullable(),
|
|
28406
28157
|
/** Input FPS from the camera (null for adaptive). */
|
|
28407
28158
|
inputFps: number().nullable(),
|
|
28408
|
-
/** Decoded FPS (null for adaptive). */
|
|
28409
|
-
decodeFps: number().nullable(),
|
|
28410
28159
|
/** Bitrate in kbps (null for adaptive). */
|
|
28411
28160
|
bitrateKbps: number().nullable()
|
|
28412
28161
|
});
|
|
@@ -38541,90 +38290,18 @@ Object.freeze({
|
|
|
38541
38290
|
addonId: null,
|
|
38542
38291
|
access: "create"
|
|
38543
38292
|
},
|
|
38544
|
-
"decoder.createSession": {
|
|
38545
|
-
capName: "decoder",
|
|
38546
|
-
capScope: "system",
|
|
38547
|
-
addonId: null,
|
|
38548
|
-
access: "view"
|
|
38549
|
-
},
|
|
38550
|
-
"decoder.destroySession": {
|
|
38551
|
-
capName: "decoder",
|
|
38552
|
-
capScope: "system",
|
|
38553
|
-
addonId: null,
|
|
38554
|
-
access: "delete"
|
|
38555
|
-
},
|
|
38556
|
-
"decoder.getFrame": {
|
|
38557
|
-
capName: "decoder",
|
|
38558
|
-
capScope: "system",
|
|
38559
|
-
addonId: null,
|
|
38560
|
-
access: "view"
|
|
38561
|
-
},
|
|
38562
38293
|
"decoder.getInfo": {
|
|
38563
38294
|
capName: "decoder",
|
|
38564
38295
|
capScope: "system",
|
|
38565
38296
|
addonId: null,
|
|
38566
38297
|
access: "view"
|
|
38567
38298
|
},
|
|
38568
|
-
"decoder.getShmStats": {
|
|
38569
|
-
capName: "decoder",
|
|
38570
|
-
capScope: "system",
|
|
38571
|
-
addonId: null,
|
|
38572
|
-
access: "view"
|
|
38573
|
-
},
|
|
38574
|
-
"decoder.getStats": {
|
|
38575
|
-
capName: "decoder",
|
|
38576
|
-
capScope: "system",
|
|
38577
|
-
addonId: null,
|
|
38578
|
-
access: "view"
|
|
38579
|
-
},
|
|
38580
|
-
"decoder.listActiveSessions": {
|
|
38581
|
-
capName: "decoder",
|
|
38582
|
-
capScope: "system",
|
|
38583
|
-
addonId: null,
|
|
38584
|
-
access: "view"
|
|
38585
|
-
},
|
|
38586
|
-
"decoder.openStream": {
|
|
38587
|
-
capName: "decoder",
|
|
38588
|
-
capScope: "system",
|
|
38589
|
-
addonId: null,
|
|
38590
|
-
access: "view"
|
|
38591
|
-
},
|
|
38592
|
-
"decoder.pullFrames": {
|
|
38593
|
-
capName: "decoder",
|
|
38594
|
-
capScope: "system",
|
|
38595
|
-
addonId: null,
|
|
38596
|
-
access: "view"
|
|
38597
|
-
},
|
|
38598
|
-
"decoder.pullHandles": {
|
|
38599
|
-
capName: "decoder",
|
|
38600
|
-
capScope: "system",
|
|
38601
|
-
addonId: null,
|
|
38602
|
-
access: "view"
|
|
38603
|
-
},
|
|
38604
|
-
"decoder.pushPacket": {
|
|
38605
|
-
capName: "decoder",
|
|
38606
|
-
capScope: "system",
|
|
38607
|
-
addonId: null,
|
|
38608
|
-
access: "view"
|
|
38609
|
-
},
|
|
38610
38299
|
"decoder.reprobeHwaccel": {
|
|
38611
38300
|
capName: "decoder",
|
|
38612
38301
|
capScope: "system",
|
|
38613
38302
|
addonId: null,
|
|
38614
38303
|
access: "create"
|
|
38615
38304
|
},
|
|
38616
|
-
"decoder.supportsCodec": {
|
|
38617
|
-
capName: "decoder",
|
|
38618
|
-
capScope: "system",
|
|
38619
|
-
addonId: null,
|
|
38620
|
-
access: "view"
|
|
38621
|
-
},
|
|
38622
|
-
"decoder.updateConfig": {
|
|
38623
|
-
capName: "decoder",
|
|
38624
|
-
capScope: "system",
|
|
38625
|
-
addonId: null,
|
|
38626
|
-
access: "view"
|
|
38627
|
-
},
|
|
38628
38305
|
"detectionPipeline.applyDeviceSettingsPatch": {
|
|
38629
38306
|
capName: "detection-pipeline",
|
|
38630
38307
|
capScope: "device",
|
|
@@ -41715,12 +41392,6 @@ Object.freeze({
|
|
|
41715
41392
|
addonId: null,
|
|
41716
41393
|
access: "delete"
|
|
41717
41394
|
},
|
|
41718
|
-
"pipelineExecutor.deleteTemplate": {
|
|
41719
|
-
capName: "pipeline-executor",
|
|
41720
|
-
capScope: "system",
|
|
41721
|
-
addonId: null,
|
|
41722
|
-
access: "delete"
|
|
41723
|
-
},
|
|
41724
41395
|
"pipelineExecutor.downloadModel": {
|
|
41725
41396
|
capName: "pipeline-executor",
|
|
41726
41397
|
capScope: "system",
|
|
@@ -41859,12 +41530,6 @@ Object.freeze({
|
|
|
41859
41530
|
addonId: null,
|
|
41860
41531
|
access: "view"
|
|
41861
41532
|
},
|
|
41862
|
-
"pipelineExecutor.listTemplates": {
|
|
41863
|
-
capName: "pipeline-executor",
|
|
41864
|
-
capScope: "system",
|
|
41865
|
-
addonId: null,
|
|
41866
|
-
access: "view"
|
|
41867
|
-
},
|
|
41868
41533
|
"pipelineExecutor.rearmInferenceDevice": {
|
|
41869
41534
|
capName: "pipeline-executor",
|
|
41870
41535
|
capScope: "system",
|
|
@@ -41889,12 +41554,6 @@ Object.freeze({
|
|
|
41889
41554
|
addonId: null,
|
|
41890
41555
|
access: "create"
|
|
41891
41556
|
},
|
|
41892
|
-
"pipelineExecutor.saveTemplate": {
|
|
41893
|
-
capName: "pipeline-executor",
|
|
41894
|
-
capScope: "system",
|
|
41895
|
-
addonId: null,
|
|
41896
|
-
access: "create"
|
|
41897
|
-
},
|
|
41898
41557
|
"pipelineExecutor.setVideoPipelineSteps": {
|
|
41899
41558
|
capName: "pipeline-executor",
|
|
41900
41559
|
capScope: "system",
|
|
@@ -41913,12 +41572,6 @@ Object.freeze({
|
|
|
41913
41572
|
addonId: null,
|
|
41914
41573
|
access: "create"
|
|
41915
41574
|
},
|
|
41916
|
-
"pipelineExecutor.updateTemplate": {
|
|
41917
|
-
capName: "pipeline-executor",
|
|
41918
|
-
capScope: "system",
|
|
41919
|
-
addonId: null,
|
|
41920
|
-
access: "create"
|
|
41921
|
-
},
|
|
41922
41575
|
"pipelineExecutor.validatePipeline": {
|
|
41923
41576
|
capName: "pipeline-executor",
|
|
41924
41577
|
capScope: "system",
|
|
@@ -41949,12 +41602,6 @@ Object.freeze({
|
|
|
41949
41602
|
addonId: null,
|
|
41950
41603
|
access: "create"
|
|
41951
41604
|
},
|
|
41952
|
-
"pipelineOrchestrator.deleteTemplate": {
|
|
41953
|
-
capName: "pipeline-orchestrator",
|
|
41954
|
-
capScope: "system",
|
|
41955
|
-
addonId: null,
|
|
41956
|
-
access: "delete"
|
|
41957
|
-
},
|
|
41958
41605
|
"pipelineOrchestrator.getAgentLoad": {
|
|
41959
41606
|
capName: "pipeline-orchestrator",
|
|
41960
41607
|
capScope: "system",
|
|
@@ -42105,12 +41752,6 @@ Object.freeze({
|
|
|
42105
41752
|
addonId: null,
|
|
42106
41753
|
access: "view"
|
|
42107
41754
|
},
|
|
42108
|
-
"pipelineOrchestrator.listTemplates": {
|
|
42109
|
-
capName: "pipeline-orchestrator",
|
|
42110
|
-
capScope: "system",
|
|
42111
|
-
addonId: null,
|
|
42112
|
-
access: "view"
|
|
42113
|
-
},
|
|
42114
41755
|
"pipelineOrchestrator.pauseForStorageMigration": {
|
|
42115
41756
|
capName: "pipeline-orchestrator",
|
|
42116
41757
|
capScope: "system",
|
|
@@ -42165,12 +41806,6 @@ Object.freeze({
|
|
|
42165
41806
|
addonId: null,
|
|
42166
41807
|
access: "create"
|
|
42167
41808
|
},
|
|
42168
|
-
"pipelineOrchestrator.saveTemplate": {
|
|
42169
|
-
capName: "pipeline-orchestrator",
|
|
42170
|
-
capScope: "system",
|
|
42171
|
-
addonId: null,
|
|
42172
|
-
access: "create"
|
|
42173
|
-
},
|
|
42174
41809
|
"pipelineOrchestrator.setAgentCapabilities": {
|
|
42175
41810
|
capName: "pipeline-orchestrator",
|
|
42176
41811
|
capScope: "system",
|
|
@@ -42279,12 +41914,6 @@ Object.freeze({
|
|
|
42279
41914
|
addonId: null,
|
|
42280
41915
|
access: "create"
|
|
42281
41916
|
},
|
|
42282
|
-
"pipelineOrchestrator.updateTemplate": {
|
|
42283
|
-
capName: "pipeline-orchestrator",
|
|
42284
|
-
capScope: "system",
|
|
42285
|
-
addonId: null,
|
|
42286
|
-
access: "create"
|
|
42287
|
-
},
|
|
42288
41917
|
"pipelineRunner.attachCamera": {
|
|
42289
41918
|
capName: "pipeline-runner",
|
|
42290
41919
|
capScope: "system",
|
|
@@ -43719,12 +43348,6 @@ Object.freeze({
|
|
|
43719
43348
|
addonId: null,
|
|
43720
43349
|
access: "view"
|
|
43721
43350
|
},
|
|
43722
|
-
"streamBroker.pullFrameHandles": {
|
|
43723
|
-
capName: "stream-broker",
|
|
43724
|
-
capScope: "system",
|
|
43725
|
-
addonId: null,
|
|
43726
|
-
access: "view"
|
|
43727
|
-
},
|
|
43728
43351
|
"streamBroker.regenerateRtspToken": {
|
|
43729
43352
|
capName: "stream-broker",
|
|
43730
43353
|
capScope: "system",
|
|
@@ -43791,12 +43414,6 @@ Object.freeze({
|
|
|
43791
43414
|
addonId: null,
|
|
43792
43415
|
access: "create"
|
|
43793
43416
|
},
|
|
43794
|
-
"streamBroker.subscribeFrames": {
|
|
43795
|
-
capName: "stream-broker",
|
|
43796
|
-
capScope: "system",
|
|
43797
|
-
addonId: null,
|
|
43798
|
-
access: "create"
|
|
43799
|
-
},
|
|
43800
43417
|
"streamBroker.unassignProfile": {
|
|
43801
43418
|
capName: "stream-broker",
|
|
43802
43419
|
capScope: "system",
|
|
@@ -43809,12 +43426,6 @@ Object.freeze({
|
|
|
43809
43426
|
addonId: null,
|
|
43810
43427
|
access: "create"
|
|
43811
43428
|
},
|
|
43812
|
-
"streamBroker.unsubscribeFrames": {
|
|
43813
|
-
capName: "stream-broker",
|
|
43814
|
-
capScope: "system",
|
|
43815
|
-
addonId: null,
|
|
43816
|
-
access: "create"
|
|
43817
|
-
},
|
|
43818
43429
|
"streamCatalog.getCatalog": {
|
|
43819
43430
|
capName: "stream-catalog",
|
|
43820
43431
|
capScope: "device",
|
|
@@ -46328,11 +45939,6 @@ Object.freeze({
|
|
|
46328
45939
|
form: "single",
|
|
46329
45940
|
optional: false
|
|
46330
45941
|
}],
|
|
46331
|
-
"decoder.createSession": [{
|
|
46332
|
-
name: "deviceId",
|
|
46333
|
-
form: "single",
|
|
46334
|
-
optional: true
|
|
46335
|
-
}],
|
|
46336
45942
|
"detectionPipeline.applyDeviceSettingsPatch": [{
|
|
46337
45943
|
name: "deviceId",
|
|
46338
45944
|
form: "single",
|
|
@@ -50473,24 +50079,6 @@ var CAMERA_STREAM_CONTROLLER = {
|
|
|
50473
50079
|
audioCodecs: ["AAC"]
|
|
50474
50080
|
}]
|
|
50475
50081
|
};
|
|
50476
|
-
/**
|
|
50477
|
-
* `Alexa.EndpointHealth` — REQUIRED on a sensor endpoint (alexa-endpointhealth;
|
|
50478
|
-
* alexa-motionsensor: "Must also implement `Alexa.EndpointHealth`"), and every
|
|
50479
|
-
* camera endpoint may carry `Alexa.MotionSensor`. Declared on every camera so
|
|
50480
|
-
* Alexa can tell an offline camera from a broken one: `connectivity` comes
|
|
50481
|
-
* from the `device-status` cap in ReportState and is pushed as a ChangeReport
|
|
50482
|
-
* on `DeviceOnline` / `DeviceOffline` by the Event Gateway.
|
|
50483
|
-
*/
|
|
50484
|
-
var ENDPOINT_HEALTH = {
|
|
50485
|
-
type: "AlexaInterface",
|
|
50486
|
-
interface: "Alexa.EndpointHealth",
|
|
50487
|
-
version: "3",
|
|
50488
|
-
properties: {
|
|
50489
|
-
supported: [{ name: "connectivity" }],
|
|
50490
|
-
proactivelyReported: true,
|
|
50491
|
-
retrievable: true
|
|
50492
|
-
}
|
|
50493
|
-
};
|
|
50494
50082
|
var DOORBELL_EVENT_SOURCE = {
|
|
50495
50083
|
type: "AlexaInterface",
|
|
50496
50084
|
interface: "Alexa.DoorbellEventSource",
|
|
@@ -50653,6 +50241,27 @@ var PTZ_TILT_MODE_CONTROLLER = ptzDirectionalModeController("ptz.tilt", "Tilt",
|
|
|
50653
50241
|
label: "Down"
|
|
50654
50242
|
}
|
|
50655
50243
|
]);
|
|
50244
|
+
/** Amazon (alexa-modecontroller): "You must include a minimum of two mode
|
|
50245
|
+
* objects." One preset made the camera's whole AddOrUpdateReport fail
|
|
50246
|
+
* schema validation, and Discover dropped the camera. */
|
|
50247
|
+
var MIN_MODE_CONTROLLER_MODES = 2;
|
|
50248
|
+
/**
|
|
50249
|
+
* Preset names as distinct mode values. Two presets with the same name (the
|
|
50250
|
+
* camera allows it: `Stanza`, `Stanza`; `CamStack Home` ×3) produced two
|
|
50251
|
+
* identical modes, and Alexa rejected the capability — "Invalid capability
|
|
50252
|
+
* received." — and with it every endpoint of the camera. First wins,
|
|
50253
|
+
* case-insensitively: the SetMode handler resolves a value to the first
|
|
50254
|
+
* preset of that name, which is the one kept.
|
|
50255
|
+
*/
|
|
50256
|
+
function distinctPresetNames(names) {
|
|
50257
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50258
|
+
return names.filter((name) => {
|
|
50259
|
+
const key = name.toLowerCase();
|
|
50260
|
+
if (seen.has(key)) return false;
|
|
50261
|
+
seen.add(key);
|
|
50262
|
+
return true;
|
|
50263
|
+
});
|
|
50264
|
+
}
|
|
50656
50265
|
function ptzPresetModeController(presetNames) {
|
|
50657
50266
|
return {
|
|
50658
50267
|
type: "AlexaInterface",
|
|
@@ -50692,13 +50301,13 @@ function buildParentCameraEndpoint(input) {
|
|
|
50692
50301
|
const capabilities = [
|
|
50693
50302
|
ALEXA_BASE_CAPABILITY,
|
|
50694
50303
|
CAMERA_STREAM_CONTROLLER,
|
|
50695
|
-
rtcSessionController(input.hasIntercom)
|
|
50696
|
-
ENDPOINT_HEALTH
|
|
50304
|
+
rtcSessionController(input.hasIntercom)
|
|
50697
50305
|
];
|
|
50698
50306
|
if (input.isDoorbell) capabilities.push(DOORBELL_EVENT_SOURCE);
|
|
50699
50307
|
if (input.hasMotion) capabilities.push(MOTION_SENSOR);
|
|
50700
50308
|
if (input.hasBattery) capabilities.push(BATTERY_LEVEL_SENSOR);
|
|
50701
|
-
|
|
50309
|
+
const presetNames = distinctPresetNames(input.ptzPresetNames);
|
|
50310
|
+
if (presetNames.length >= MIN_MODE_CONTROLLER_MODES) capabilities.push(ptzPresetModeController(presetNames));
|
|
50702
50311
|
if (input.hasPtz) {
|
|
50703
50312
|
capabilities.push(PTZ_PAN_MODE_CONTROLLER);
|
|
50704
50313
|
capabilities.push(PTZ_TILT_MODE_CONTROLLER);
|
|
@@ -50837,6 +50446,12 @@ function buildAlarmPanelEndpoint(input) {
|
|
|
50837
50446
|
};
|
|
50838
50447
|
}
|
|
50839
50448
|
//#endregion
|
|
50449
|
+
//#region src/handlers/ptz-preset-recallable.ts
|
|
50450
|
+
var RECALLABLE_FUNCTIONS = new Set(["home"]);
|
|
50451
|
+
function isAlexaRecallablePreset(preset) {
|
|
50452
|
+
return preset.fn === null || RECALLABLE_FUNCTIONS.has(preset.fn);
|
|
50453
|
+
}
|
|
50454
|
+
//#endregion
|
|
50840
50455
|
//#region src/handlers/discovery.ts
|
|
50841
50456
|
var discoveryPayloadSchema = DiscoveryDirectiveSchema.shape.payload;
|
|
50842
50457
|
/** Devices built at once in `handleDiscovery` — latency-bound tRPC reads, so
|
|
@@ -51024,7 +50639,7 @@ async function loadBoundDeviceInfo(device, api) {
|
|
|
51024
50639
|
};
|
|
51025
50640
|
}
|
|
51026
50641
|
async function fetchPtzPresetNames(deviceId, api) {
|
|
51027
|
-
return (await api.ptz.getPresets.query({ deviceId })).map((p) => p.name).filter((n) => n.length > 0);
|
|
50642
|
+
return (await api.ptz.getPresets.query({ deviceId })).filter(isAlexaRecallablePreset).map((p) => p.name).filter((n) => n.length > 0);
|
|
51028
50643
|
}
|
|
51029
50644
|
function classifyChildKind(deviceType, role) {
|
|
51030
50645
|
if (role === "floodlight" || role === "spotlight" || role === "nightvision") return "light";
|
|
@@ -51424,8 +51039,8 @@ async function handleSetMode(header, endpointRaw, payloadRaw, deps, _callerIdent
|
|
|
51424
51039
|
if (!mode.startsWith(PTZ_PRESET_MODE_PREFIX)) return errorEnvelope(header, "INVALID_DIRECTIVE", `mode '${mode}' is not a ptz.preset mode`);
|
|
51425
51040
|
const presetName = mode.slice(11);
|
|
51426
51041
|
if (presetName.length === 0) return errorEnvelope(header, "INVALID_DIRECTIVE", "preset name missing after prefix");
|
|
51427
|
-
const preset = (await api.ptz.getPresets.query({ deviceId: parsedId.deviceId })).find((p) => p.name === presetName);
|
|
51428
|
-
if (!preset) return errorEnvelope(header, "INVALID_DIRECTIVE", `preset '${presetName}' not
|
|
51042
|
+
const preset = (await api.ptz.getPresets.query({ deviceId: parsedId.deviceId })).find((p) => p.name === presetName && isAlexaRecallablePreset(p));
|
|
51043
|
+
if (!preset) return errorEnvelope(header, "INVALID_DIRECTIVE", `preset '${presetName}' is not a recallable preset on device ${parsedId.deviceId}`);
|
|
51429
51044
|
await api.ptz.goToPreset.mutate({
|
|
51430
51045
|
deviceId: parsedId.deviceId,
|
|
51431
51046
|
presetId: preset.id
|
|
@@ -51517,20 +51132,6 @@ async function collectCameraProperties(api, deviceId, properties, timeOfSample,
|
|
|
51517
51132
|
timeOfSample,
|
|
51518
51133
|
uncertaintyInMilliseconds: 0
|
|
51519
51134
|
});
|
|
51520
|
-
const online = boolField(await api.deviceStatus.getStatus.query({ deviceId }).catch((err) => {
|
|
51521
|
-
logger.warn("alexa report-state: deviceStatus.getStatus failed — connectivity omitted", {
|
|
51522
|
-
tags: { deviceId },
|
|
51523
|
-
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
51524
|
-
});
|
|
51525
|
-
return null;
|
|
51526
|
-
}), "online");
|
|
51527
|
-
if (online !== null) properties.push({
|
|
51528
|
-
namespace: "Alexa.EndpointHealth",
|
|
51529
|
-
name: "connectivity",
|
|
51530
|
-
value: { value: online ? "OK" : "UNREACHABLE" },
|
|
51531
|
-
timeOfSample,
|
|
51532
|
-
uncertaintyInMilliseconds: 0
|
|
51533
|
-
});
|
|
51534
51135
|
const detected = boolField(await api.motion.getStatus.query({ deviceId }).catch((err) => {
|
|
51535
51136
|
logger.info("alexa report-state: motion.getStatus skipped", { meta: {
|
|
51536
51137
|
deviceId,
|
|
@@ -53487,7 +53088,7 @@ function buildAlexaOauthIntegration(publicHubUrl) {
|
|
|
53487
53088
|
* client id and SECRET, on the theory that a per-account refresh token was the
|
|
53488
53089
|
* real gate. The package is public on npm, so that secret was published with
|
|
53489
53090
|
* every version and has to be rotated. Since D753 the secret lives only in the
|
|
53490
|
-
* skill's Lambda (
|
|
53091
|
+
* skill's Lambda (SSM Parameter Store SecureString, D761); the hub gets short-lived Event Gateway
|
|
53491
53092
|
* tokens from the Lambda's broker (`broker-client.ts`) with a per-link
|
|
53492
53093
|
* credential. `scripts/check-no-client-secrets.ts` keeps it that way.
|
|
53493
53094
|
*
|
|
@@ -54518,7 +54119,7 @@ var ExportAlexaAddon = class extends BaseAddon {
|
|
|
54518
54119
|
content: [
|
|
54519
54120
|
"Public skill (default): enable the \"CamStack\" skill in the Alexa app and link your account — no Amazon developer setup is needed. A single published skill + hosted Lambda route to this hub using its public HTTPS URL (baked into every JWT).",
|
|
54520
54121
|
"The skill's Lambda keeps the Amazon credentials: this hub never holds an LWA client secret. It receives short-lived event tokens from the Lambda's token broker with a credential that is unique to this link.",
|
|
54521
|
-
"Custom skill: switch \"Alexa skill\" below to Custom, enter your skill id, and deploy the skill Lambda from this addon's lambda-template in your own AWS account (your LWA credentials go into
|
|
54122
|
+
"Custom skill: switch \"Alexa skill\" below to Custom, enter your skill id, and deploy the skill Lambda from this addon's lambda-template in your own AWS account (your LWA credentials go into SSM Parameter Store there, not here).",
|
|
54522
54123
|
"Either way this hub must be reachable from the public internet (Cloudflare Tunnel, Tailscale Funnel, …). The \"External address\" picker selects which detected endpoint the Lambda calls back on — press \"Refresh external addresses\" after setting up a new tunnel."
|
|
54523
54124
|
].join("\n")
|
|
54524
54125
|
},
|
|
@@ -54585,7 +54186,7 @@ var ExportAlexaAddon = class extends BaseAddon {
|
|
|
54585
54186
|
key: "__custom-skill-info",
|
|
54586
54187
|
label: "Your skill Lambda",
|
|
54587
54188
|
variant: "info",
|
|
54588
|
-
content: "Proactive events (doorbell, motion, battery, device-list updates) are authorised by YOUR skill Lambda: it keeps the \"Send Alexa Events\" LWA client id/secret in
|
|
54189
|
+
content: "Proactive events (doorbell, motion, battery, device-list updates) are authorised by YOUR skill Lambda: it keeps the \"Send Alexa Events\" LWA client id/secret in SSM Parameter Store and hands this hub short-lived tokens. Nothing to paste here — see the custom-skill setup guide."
|
|
54589
54190
|
}] : [{
|
|
54590
54191
|
type: "info",
|
|
54591
54192
|
key: "__public-skill-info",
|