@camstack/addon-export-alexa 1.2.134 → 1.2.136
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 +146 -482
- package/dist/export-alexa.addon.mjs +146 -482
- 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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as crypto$1 from "node:crypto";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
|
-
//#region ../types/dist/event-category-
|
|
3
|
+
//#region ../types/dist/event-category-B_0XEcLF.mjs
|
|
4
4
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
5
5
|
EventCategory["SystemBoot"] = "system.boot";
|
|
6
6
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -501,15 +501,6 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
501
501
|
EventCategory["AgentWsDisconnected"] = "agent.ws.disconnected";
|
|
502
502
|
EventCategory["AgentBackupActivated"] = "agent.backup.activated";
|
|
503
503
|
EventCategory["OrchestrationSettingsUpdated"] = "orchestration.settings-updated";
|
|
504
|
-
/**
|
|
505
|
-
* Per-agent hwaccel preference changed (user override set, cleared, or
|
|
506
|
-
* re-probed). Observability event — decoders pull the current pref at
|
|
507
|
-
* `createSession`, so running sessions keep their current backend until
|
|
508
|
-
* they rotate naturally (camera add/remove, stream restart). Future
|
|
509
|
-
* work can wire a listener in stream-broker that force-rotates live
|
|
510
|
-
* sessions; for now this event powers logs + admin-UI toast feedback.
|
|
511
|
-
*/
|
|
512
|
-
EventCategory["PipelineAgentHwaccelChanged"] = "pipeline.agent-hwaccel-changed";
|
|
513
504
|
EventCategory["MotionAnalysis"] = "detection.motion-analysis";
|
|
514
505
|
/** All raw motion zones from CCL before minArea filter — for UI debug overlay. */
|
|
515
506
|
EventCategory["MotionZonesRaw"] = "detection.motion-zones-raw";
|
|
@@ -5380,7 +5371,7 @@ var ZodIssueCode = {
|
|
|
5380
5371
|
var ZodFirstPartyTypeKind;
|
|
5381
5372
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5382
5373
|
//#endregion
|
|
5383
|
-
//#region ../types/dist/sleep-
|
|
5374
|
+
//#region ../types/dist/sleep-BNeXenvr.mjs
|
|
5384
5375
|
/**
|
|
5385
5376
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5386
5377
|
* window to float samples (D455).
|
|
@@ -6746,32 +6737,12 @@ object({
|
|
|
6746
6737
|
audioCodec: string().optional(),
|
|
6747
6738
|
metadata: record(string(), unknown()).readonly().optional()
|
|
6748
6739
|
});
|
|
6749
|
-
var EncodedPacketSchema = object({
|
|
6750
|
-
type: _enum(["video", "audio"]),
|
|
6751
|
-
data: _instanceof(Uint8Array),
|
|
6752
|
-
pts: number(),
|
|
6753
|
-
dts: number(),
|
|
6754
|
-
keyframe: boolean(),
|
|
6755
|
-
codec: string()
|
|
6756
|
-
});
|
|
6757
|
-
var DecodedFrameSchema = object({
|
|
6758
|
-
data: _instanceof(Uint8Array),
|
|
6759
|
-
width: number(),
|
|
6760
|
-
height: number(),
|
|
6761
|
-
format: _enum([
|
|
6762
|
-
"jpeg",
|
|
6763
|
-
"rgb",
|
|
6764
|
-
"bgr",
|
|
6765
|
-
"yuv420",
|
|
6766
|
-
"gray"
|
|
6767
|
-
]),
|
|
6768
|
-
timestamp: number()
|
|
6769
|
-
});
|
|
6770
6740
|
/**
|
|
6771
6741
|
* Wire schema for `FrameHandle` — a zero-pixel, serialisable reference to a
|
|
6772
6742
|
* frame in a shared-memory ring (Phase 5 / D9). Mirrors the `FrameHandle` TS
|
|
6773
|
-
* interface in `interfaces/frame-handle.ts` field-for-field so a
|
|
6774
|
-
*
|
|
6743
|
+
* interface in `interfaces/frame-handle.ts` field-for-field so a cap method
|
|
6744
|
+
* (the runner's native-crop and pipeline-executor inputs) can carry handles
|
|
6745
|
+
* over tRPC / Moleculer.
|
|
6775
6746
|
*
|
|
6776
6747
|
* The `satisfies` assertion below pins this schema to the interface: if a
|
|
6777
6748
|
* field is added to / removed from `FrameHandle` without a matching schema
|
|
@@ -6797,50 +6768,6 @@ var FrameHandleSchema = object({
|
|
|
6797
6768
|
slotCount: number().int().positive()
|
|
6798
6769
|
});
|
|
6799
6770
|
/**
|
|
6800
|
-
* Pixel format a frame-handle subscriber can request from the broker
|
|
6801
|
-
* (Phase 5 / D9). The packed, raster subset of `FrameFormat` — the formats a
|
|
6802
|
-
* `frameSink: 'shm'` decoder session can write into a `FrameRing` slot.
|
|
6803
|
-
* `jpeg` is excluded: a variable-length stream is not a fixed-stride ring
|
|
6804
|
-
* payload, and no decoded-frame consumer requests it over the shm plane.
|
|
6805
|
-
*/
|
|
6806
|
-
var FrameHandleFormatSchema = _enum([
|
|
6807
|
-
"rgb",
|
|
6808
|
-
"bgr",
|
|
6809
|
-
"yuv420",
|
|
6810
|
-
"gray"
|
|
6811
|
-
]);
|
|
6812
|
-
/**
|
|
6813
|
-
* Input for `stream-broker.subscribeFrames` (Phase 5 / D9). A consumer asks the
|
|
6814
|
-
* broker for a `FrameHandle` stream of one `format`; the broker maintains one
|
|
6815
|
-
* shared-memory ring per `(brokerId, format)` actually requested, so a `gray`
|
|
6816
|
-
* subscriber (motion) and an `rgb` subscriber (detection) each read the format
|
|
6817
|
-
* they asked for with no broker-side conversion.
|
|
6818
|
-
*/
|
|
6819
|
-
var SubscribeFramesInputSchema = object({
|
|
6820
|
-
brokerId: string(),
|
|
6821
|
-
format: FrameHandleFormatSchema,
|
|
6822
|
-
/**
|
|
6823
|
-
* Optional reader-side cadence hint in frames per second. The broker does
|
|
6824
|
-
* NOT throttle — latest-wins ring reads drop frames implicitly for a slow
|
|
6825
|
-
* consumer. The value is echoed back in `SubscribeFramesResult.maxFps` so
|
|
6826
|
-
* the consumer can pace its own `pullFrameHandles` polling.
|
|
6827
|
-
*/
|
|
6828
|
-
maxFps: number().positive().optional(),
|
|
6829
|
-
/** Short caller-identity tag (`motion`, `detection`, …) for diagnostics. */
|
|
6830
|
-
tag: string().optional()
|
|
6831
|
-
});
|
|
6832
|
-
/**
|
|
6833
|
-
* Result of `stream-broker.subscribeFrames`. The consumer then polls
|
|
6834
|
-
* `pullFrameHandles({ subscriptionId, maxCount })` and feeds each returned
|
|
6835
|
-
* `FrameHandle` to a `FrameRingReader`.
|
|
6836
|
-
*/
|
|
6837
|
-
var SubscribeFramesResultSchema = object({
|
|
6838
|
-
/** Opaque id the consumer passes to `pullFrameHandles` / `unsubscribeFrames`. */
|
|
6839
|
-
subscriptionId: string(),
|
|
6840
|
-
/** Reader-side cadence hint (frames/s) — echoes `SubscribeFramesInput.maxFps`. */
|
|
6841
|
-
maxFps: number().nonnegative()
|
|
6842
|
-
});
|
|
6843
|
-
/**
|
|
6844
6771
|
* Wire schema for a decoded audio chunk (Phase 5 / D9). Mirrors the
|
|
6845
6772
|
* `DecodedAudioChunk` TS interface in `interfaces/stream-broker.ts`: PCM
|
|
6846
6773
|
* sample bytes plus the track parameters a consumer needs to interpret them.
|
|
@@ -6848,8 +6775,8 @@ var SubscribeFramesResultSchema = object({
|
|
|
6848
6775
|
* Audio chunks are tiny (a ~500ms AudioCodecSession window is a few KB of
|
|
6849
6776
|
* Float32 PCM), so unlike video frames they ship their bytes INLINE over
|
|
6850
6777
|
* tRPC / Moleculer — no shared-memory plane. `data` is typed `Uint8Array`
|
|
6851
|
-
* (the wire-serialisable supertype of `Buffer`)
|
|
6852
|
-
*
|
|
6778
|
+
* (the wire-serialisable supertype of `Buffer`); a `Buffer` is assignable to
|
|
6779
|
+
* it.
|
|
6853
6780
|
*/
|
|
6854
6781
|
var AudioChunkFormatSchema = _enum(AUDIO_CHUNK_FORMATS);
|
|
6855
6782
|
var DecodedAudioChunkSchema = object({
|
|
@@ -6867,11 +6794,10 @@ var DecodedAudioChunkSchema = object({
|
|
|
6867
6794
|
format: AudioChunkFormatSchema.optional()
|
|
6868
6795
|
});
|
|
6869
6796
|
/**
|
|
6870
|
-
* Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9).
|
|
6871
|
-
*
|
|
6872
|
-
*
|
|
6873
|
-
*
|
|
6874
|
-
* `pullAudioChunks`.
|
|
6797
|
+
* Input for `stream-broker.subscribeAudioChunks` (Phase 5 / D9). Audio ships
|
|
6798
|
+
* its bytes inline: a consumer asks the broker for the decoded audio-chunk
|
|
6799
|
+
* stream of one broker; the broker keeps a per-subscription bounded FIFO queue
|
|
6800
|
+
* the consumer drains via `pullAudioChunks`.
|
|
6875
6801
|
*/
|
|
6876
6802
|
var SubscribeAudioChunksInputSchema = object({
|
|
6877
6803
|
brokerId: string(),
|
|
@@ -6902,9 +6828,7 @@ var BrokerStatsSchema = object({
|
|
|
6902
6828
|
"stopped"
|
|
6903
6829
|
]),
|
|
6904
6830
|
inputFps: number(),
|
|
6905
|
-
decodeFps: number(),
|
|
6906
6831
|
encodedSubscribers: number(),
|
|
6907
|
-
decodedSubscribers: number(),
|
|
6908
6832
|
uptimeMs: number(),
|
|
6909
6833
|
bitrateKbps: number(),
|
|
6910
6834
|
idrIntervalMs: number(),
|
|
@@ -6917,14 +6841,6 @@ var BrokerStatsSchema = object({
|
|
|
6917
6841
|
preBufferMs: number(),
|
|
6918
6842
|
preBufferPackets: number(),
|
|
6919
6843
|
/**
|
|
6920
|
-
* Moleculer node id of the decoder provider currently servicing this
|
|
6921
|
-
* stream's decoded subscribers. `null` until the deferred decoder is
|
|
6922
|
-
* created (no decoded clients yet, or codec not detected). Surfaces the
|
|
6923
|
-
* runtime decoder placement so the UI can show "Decoder: <agent>" without
|
|
6924
|
-
* a separate cap call per broker.
|
|
6925
|
-
*/
|
|
6926
|
-
decoderNodeId: string().nullable(),
|
|
6927
|
-
/**
|
|
6928
6844
|
* Detected audio track parameters from the RTSP DESCRIBE / SDP. `null`
|
|
6929
6845
|
* when the stream has no audio track or the broker is in cold start.
|
|
6930
6846
|
* `supported = false` means the codec was detected but the local
|
|
@@ -10447,70 +10363,6 @@ var StorageLocationDeclarationSchema = object({
|
|
|
10447
10363
|
"backup"
|
|
10448
10364
|
]).optional()
|
|
10449
10365
|
});
|
|
10450
|
-
var DecoderStatsSchema = object({
|
|
10451
|
-
inputFps: number(),
|
|
10452
|
-
outputFps: number(),
|
|
10453
|
-
avgDecodeTimeMs: number(),
|
|
10454
|
-
droppedFrames: number(),
|
|
10455
|
-
/**
|
|
10456
|
-
* Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
|
|
10457
|
-
* lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
|
|
10458
|
-
* the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
|
|
10459
|
-
* is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
|
|
10460
|
-
*/
|
|
10461
|
-
lagMs: number().optional(),
|
|
10462
|
-
effectiveFps: number().optional(),
|
|
10463
|
-
adaptiveFps: number().optional()
|
|
10464
|
-
});
|
|
10465
|
-
var DecoderSessionConfigSchema = object({
|
|
10466
|
-
codec: string(),
|
|
10467
|
-
maxFps: number().default(0),
|
|
10468
|
-
outputFormat: _enum([
|
|
10469
|
-
"jpeg",
|
|
10470
|
-
"rgb",
|
|
10471
|
-
"bgr",
|
|
10472
|
-
"yuv420",
|
|
10473
|
-
"gray"
|
|
10474
|
-
]).default("jpeg"),
|
|
10475
|
-
scale: number().default(1),
|
|
10476
|
-
width: number().optional(),
|
|
10477
|
-
height: number().optional(),
|
|
10478
|
-
/**
|
|
10479
|
-
* Identifier of the camera this decoder session serves. Optional
|
|
10480
|
-
* because the cap is generic (any caller could request decode), but
|
|
10481
|
-
* stream-broker passes it so decoder logs include `deviceId` for
|
|
10482
|
-
* per-camera filtering when diagnosing failures (e.g. node-av
|
|
10483
|
-
* sendPacket errors on a single hung camera).
|
|
10484
|
-
*/
|
|
10485
|
-
deviceId: number().int().nonnegative().optional(),
|
|
10486
|
-
/**
|
|
10487
|
-
* Free-form tag for log scoping. Stream-broker uses
|
|
10488
|
-
* `broker:<deviceId>/<profile>`. Decoder session logger surfaces it
|
|
10489
|
-
* on every line so `grep tag=broker:5/high` filters one camera
|
|
10490
|
-
* profile cleanly.
|
|
10491
|
-
*/
|
|
10492
|
-
tag: string().optional(),
|
|
10493
|
-
/**
|
|
10494
|
-
* Where the session delivers decoded frames (Phase 5 / D9):
|
|
10495
|
-
*
|
|
10496
|
-
* - `'callback'` (default) — the legacy pixel path: decoded frames are
|
|
10497
|
-
* buffered as `DecodedFrame`s and drained via `pullFrames`.
|
|
10498
|
-
* - `'shm'` — the shared-memory frame plane: decoded frames are written
|
|
10499
|
-
* into an OS shared-memory ring and drained as zero-pixel
|
|
10500
|
-
* `FrameHandle`s via `pullHandles`. A session is one mode or the
|
|
10501
|
-
* other — `pullFrames` returns nothing for an `'shm'` session and
|
|
10502
|
-
* `pullHandles` returns nothing for a `'callback'` session.
|
|
10503
|
-
*/
|
|
10504
|
-
frameSink: _enum(["callback", "shm"]).default("callback"),
|
|
10505
|
-
/**
|
|
10506
|
-
* Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
|
|
10507
|
-
* a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
|
|
10508
|
-
* real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
|
|
10509
|
-
* stream-broker's `streamingDebug` gate — off by default so production logs
|
|
10510
|
-
* stay quiet and the emit path pays zero per-frame cost when disabled.
|
|
10511
|
-
*/
|
|
10512
|
-
debug: boolean().optional()
|
|
10513
|
-
});
|
|
10514
10366
|
/**
|
|
10515
10367
|
* Per-component log CHANNELS — the gate a hot path consults, and the registry
|
|
10516
10368
|
* an addon declares its channels in.
|
|
@@ -12771,13 +12623,6 @@ var BrokerRtspClientSchema = object({
|
|
|
12771
12623
|
lastRtpAt: number(),
|
|
12772
12624
|
bytesSent: number()
|
|
12773
12625
|
});
|
|
12774
|
-
var BrokerDecodedClientSchema = object({
|
|
12775
|
-
tag: string(),
|
|
12776
|
-
subscribedAt: number(),
|
|
12777
|
-
maxFps: number(),
|
|
12778
|
-
framesDelivered: number(),
|
|
12779
|
-
framesDropped: number()
|
|
12780
|
-
});
|
|
12781
12626
|
var BrokerAudioClientSchema = object({
|
|
12782
12627
|
tag: string(),
|
|
12783
12628
|
subscribedAt: number(),
|
|
@@ -12869,7 +12714,6 @@ var BrokerEncodedClientSchema = object({
|
|
|
12869
12714
|
});
|
|
12870
12715
|
var BrokerClientsSchema = object({
|
|
12871
12716
|
rtsp: array(BrokerRtspClientSchema).readonly(),
|
|
12872
|
-
decoded: array(BrokerDecodedClientSchema).readonly(),
|
|
12873
12717
|
audio: array(BrokerAudioClientSchema).readonly(),
|
|
12874
12718
|
encoded: array(BrokerEncodedClientSchema).readonly(),
|
|
12875
12719
|
pipeClients: number(),
|
|
@@ -13238,11 +13082,7 @@ method(object({
|
|
|
13238
13082
|
auth: "admin"
|
|
13239
13083
|
}), method(object({ brokerId: string() }), BrokerClientsSchema), method(object({
|
|
13240
13084
|
brokerId: string(),
|
|
13241
|
-
channel: _enum([
|
|
13242
|
-
"rtsp",
|
|
13243
|
-
"decoded",
|
|
13244
|
-
"audio"
|
|
13245
|
-
]),
|
|
13085
|
+
channel: _enum(["rtsp", "audio"]),
|
|
13246
13086
|
handle: string()
|
|
13247
13087
|
}), object({ killed: boolean() }), {
|
|
13248
13088
|
kind: "mutation",
|
|
@@ -13277,10 +13117,7 @@ method(object({
|
|
|
13277
13117
|
}), method(SubscribeAudioChunksInputSchema, SubscribeAudioChunksResultSchema, { kind: "mutation" }), method(object({
|
|
13278
13118
|
subscriptionId: string(),
|
|
13279
13119
|
maxCount: number().int().positive().default(8)
|
|
13280
|
-
}), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(
|
|
13281
|
-
subscriptionId: string(),
|
|
13282
|
-
maxCount: number().int().positive().default(4)
|
|
13283
|
-
}), array(FrameHandleSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
|
|
13120
|
+
}), array(DecodedAudioChunkSchema).readonly()), method(object({ subscriptionId: string() }), object({ released: boolean() }), { kind: "mutation" }), method(object({
|
|
13284
13121
|
brokerId: string(),
|
|
13285
13122
|
seconds: number().min(0).max(30)
|
|
13286
13123
|
}), _void(), {
|
|
@@ -14437,54 +14274,12 @@ id: union([string(), number()]) }), {
|
|
|
14437
14274
|
kind: "mutation",
|
|
14438
14275
|
auth: "admin"
|
|
14439
14276
|
});
|
|
14440
|
-
|
|
14441
|
-
* shm ring usage stats for a `frameSink: 'shm'` decoder session —
|
|
14442
|
-
* exposed via `decoder.getShmStats` so downstream consumers can
|
|
14443
|
-
* observe ring pressure (slot count, byte budget, hit/miss ratio).
|
|
14444
|
-
*/
|
|
14445
|
-
var ShmRingStatsSchema = object({
|
|
14446
|
-
sessionId: string(),
|
|
14447
|
-
slotCount: number().int(),
|
|
14448
|
-
slotByteLength: number().int(),
|
|
14449
|
-
segmentBytes: number().int(),
|
|
14450
|
-
budgetMb: number().int(),
|
|
14451
|
-
framesWritten: number().int(),
|
|
14452
|
-
getFrameHits: number().int(),
|
|
14453
|
-
getFrameMisses: number().int()
|
|
14454
|
-
});
|
|
14455
|
-
method(object({ codec: string() }), boolean()), method(_void(), object({
|
|
14277
|
+
method(_void(), object({
|
|
14456
14278
|
id: string(),
|
|
14457
14279
|
name: string(),
|
|
14458
|
-
isPullMode: boolean().optional(),
|
|
14459
|
-
priority: number().optional(),
|
|
14460
14280
|
hwaccel: string().optional(),
|
|
14461
14281
|
probedBestHwaccel: string().optional()
|
|
14462
|
-
})), method(
|
|
14463
|
-
sessionId: string(),
|
|
14464
|
-
nodeId: string()
|
|
14465
|
-
})), method(object({ sessionId: string() }), _void()), method(object({
|
|
14466
|
-
sessionId: string(),
|
|
14467
|
-
packet: EncodedPacketSchema
|
|
14468
|
-
}), _void()), method(object({
|
|
14469
|
-
sessionId: string(),
|
|
14470
|
-
url: string()
|
|
14471
|
-
}), _void()), method(object({
|
|
14472
|
-
sessionId: string(),
|
|
14473
|
-
maxCount: number().default(1),
|
|
14474
|
-
waitMs: number().optional()
|
|
14475
|
-
}), array(DecodedFrameSchema)), method(object({
|
|
14476
|
-
sessionId: string(),
|
|
14477
|
-
maxCount: number().default(1),
|
|
14478
|
-
waitMs: number().optional()
|
|
14479
|
-
}), array(FrameHandleSchema)), method(object({ handle: FrameHandleSchema }), DecodedFrameSchema.nullable()), method(object({ sessionId: string() }), ShmRingStatsSchema.nullable()), method(object({
|
|
14480
|
-
sessionId: string(),
|
|
14481
|
-
config: DecoderSessionConfigSchema.partial()
|
|
14482
|
-
}), _void()), method(object({ sessionId: string() }), DecoderStatsSchema), method(_void(), array(object({
|
|
14483
|
-
sessionId: string(),
|
|
14484
|
-
codec: string(),
|
|
14485
|
-
outputFormat: string(),
|
|
14486
|
-
createdAtMs: number()
|
|
14487
|
-
})).readonly()), method(_void(), object({ backend: string() }), {
|
|
14282
|
+
})), method(_void(), object({ backend: string() }), {
|
|
14488
14283
|
kind: "mutation",
|
|
14489
14284
|
auth: "admin"
|
|
14490
14285
|
});
|
|
@@ -21545,8 +21340,8 @@ Object.freeze(Object.fromEntries([{
|
|
|
21545
21340
|
var CLUSTER_STEP_SETTING_FIELDS = [{
|
|
21546
21341
|
stepId: "face-embedding",
|
|
21547
21342
|
key: "minLandmarkFaceSize",
|
|
21548
|
-
label: "Min face size
|
|
21549
|
-
description: "
|
|
21343
|
+
label: "Min face size to embed (detection-frame px)",
|
|
21344
|
+
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.",
|
|
21550
21345
|
type: "slider",
|
|
21551
21346
|
min: 0,
|
|
21552
21347
|
max: 64,
|
|
@@ -23598,21 +23393,6 @@ var PipelineDefaultStepSchema = lazy(() => object({
|
|
|
23598
23393
|
group: string().optional(),
|
|
23599
23394
|
settings: record(string(), unknown()).optional()
|
|
23600
23395
|
}));
|
|
23601
|
-
var PipelineTemplateStepSchema = lazy(() => object({
|
|
23602
|
-
addonId: string(),
|
|
23603
|
-
enabled: boolean(),
|
|
23604
|
-
modelId: string(),
|
|
23605
|
-
children: array(PipelineTemplateStepSchema).readonly(),
|
|
23606
|
-
settings: record(string(), unknown()).optional()
|
|
23607
|
-
}));
|
|
23608
|
-
var PipelineTemplateSchema$1 = object({
|
|
23609
|
-
id: string(),
|
|
23610
|
-
name: string(),
|
|
23611
|
-
createdAt: string(),
|
|
23612
|
-
updatedAt: string(),
|
|
23613
|
-
engine: PipelineEngineChoiceSchema,
|
|
23614
|
-
steps: array(PipelineTemplateStepSchema).readonly()
|
|
23615
|
-
});
|
|
23616
23396
|
var PipelineModelOptionSchema = object({
|
|
23617
23397
|
id: string(),
|
|
23618
23398
|
name: string(),
|
|
@@ -23824,15 +23604,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
|
|
|
23824
23604
|
}), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({
|
|
23825
23605
|
steps: array(PipelineStepInputSchema),
|
|
23826
23606
|
deviceKey: string().optional()
|
|
23827
|
-
}), PipelineValidationResultSchema), method(_void(),
|
|
23828
|
-
name: string(),
|
|
23829
|
-
steps: array(PipelineTemplateStepSchema).readonly(),
|
|
23830
|
-
engine: PipelineEngineChoiceSchema
|
|
23831
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({
|
|
23832
|
-
id: string(),
|
|
23833
|
-
name: string().optional(),
|
|
23834
|
-
steps: array(PipelineTemplateStepSchema).readonly().optional()
|
|
23835
|
-
}), PipelineTemplateSchema$1, { kind: "mutation" }), method(object({ id: string() }), _void(), { kind: "mutation" }), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
23607
|
+
}), PipelineValidationResultSchema), method(_void(), InferenceCapabilitiesBridge), method(object({ addonId: string() }), ModelAvailabilityListBridge), method(object({
|
|
23836
23608
|
addonId: string(),
|
|
23837
23609
|
modelId: string(),
|
|
23838
23610
|
format: ModelFormatSchema$2
|
|
@@ -25242,14 +25014,15 @@ var RunnerLocalLoadSchema = object({
|
|
|
25242
25014
|
* Per-inference-device live load (multi-device C4). One entry per deviceKey
|
|
25243
25015
|
* this runner currently has attached cameras on, so the orchestrator's second
|
|
25244
25016
|
* `balance()` pass (over a node's devices) weights on real per-pool session
|
|
25245
|
-
* counts. Empty on single-device / pre-multi-device runners.
|
|
25246
|
-
* per
|
|
25017
|
+
* counts. Empty on single-device / pre-multi-device runners. There is no
|
|
25018
|
+
* per-device queue depth: the inference pool's backlog has no accessor, and
|
|
25019
|
+
* a field that always read 0 was removed rather than shown as a measurement
|
|
25020
|
+
* (D762).
|
|
25247
25021
|
*/
|
|
25248
25022
|
devices: array(object({
|
|
25249
25023
|
deviceKey: string(),
|
|
25250
25024
|
backend: string(),
|
|
25251
|
-
attachedCameras: number()
|
|
25252
|
-
queueDepthTotal: number()
|
|
25025
|
+
attachedCameras: number()
|
|
25253
25026
|
})).default([]),
|
|
25254
25027
|
/** Hardware capability flags reported by this node. */
|
|
25255
25028
|
hardware: object({
|
|
@@ -25463,14 +25236,6 @@ var CameraPipelineConfigSchema = object({
|
|
|
25463
25236
|
settings: record(string(), unknown()).readonly().optional()
|
|
25464
25237
|
}).nullable().optional()
|
|
25465
25238
|
});
|
|
25466
|
-
var PipelineTemplateSchema = object({
|
|
25467
|
-
id: string(),
|
|
25468
|
-
name: string(),
|
|
25469
|
-
description: string().optional(),
|
|
25470
|
-
config: CameraPipelineConfigSchema,
|
|
25471
|
-
createdAt: string(),
|
|
25472
|
-
updatedAt: string()
|
|
25473
|
-
});
|
|
25474
25239
|
var DeviceStepConfigSchema = object({
|
|
25475
25240
|
modelId: string().optional(),
|
|
25476
25241
|
settings: record(string(), unknown()).optional(),
|
|
@@ -25580,7 +25345,10 @@ var PipelineAssignmentSchema = object({
|
|
|
25580
25345
|
});
|
|
25581
25346
|
/**
|
|
25582
25347
|
* Per-agent load summary surfaced to the load balancer + dashboards.
|
|
25583
|
-
* Aggregated from each runner's `getLocalLoad` cap call.
|
|
25348
|
+
* Aggregated from each runner's `getLocalLoad` cap call. In the
|
|
25349
|
+
* `getAgentLoad` report, a single-device node's default-pool sessions (no
|
|
25350
|
+
* `deviceKey`) are credited to its one eligible device in `load.devices` —
|
|
25351
|
+
* the default pool IS that device (D745); the balancer's census stays raw.
|
|
25584
25352
|
*/
|
|
25585
25353
|
var AgentLoadSummarySchema = object({
|
|
25586
25354
|
nodeId: string(),
|
|
@@ -25669,26 +25437,27 @@ var CameraBrokerStatusSchema = object({
|
|
|
25669
25437
|
width: number(),
|
|
25670
25438
|
height: number(),
|
|
25671
25439
|
subscribers: number(),
|
|
25672
|
-
|
|
25673
|
-
|
|
25440
|
+
/**
|
|
25441
|
+
* Encoded packets/s the broker receives from the camera. null when the
|
|
25442
|
+
* broker's stats read failed — unknown, never 0 (a 0 here reads as a stall).
|
|
25443
|
+
* There is no output rate: decoding runs in the session decode workers, not
|
|
25444
|
+
* in the broker, so the broker's own decoded-frame rate is 0 on every live
|
|
25445
|
+
* camera and is not served (D758).
|
|
25446
|
+
*/
|
|
25447
|
+
inFps: number().nullable()
|
|
25674
25448
|
})).readonly(),
|
|
25675
25449
|
webrtcSessions: number(),
|
|
25676
25450
|
rtspRestream: boolean()
|
|
25677
25451
|
});
|
|
25678
|
-
/**
|
|
25679
|
-
|
|
25680
|
-
|
|
25681
|
-
|
|
25682
|
-
|
|
25683
|
-
|
|
25684
|
-
|
|
25685
|
-
|
|
25686
|
-
var CameraDecoderStatusSchema = object({
|
|
25687
|
-
nodeId: string(),
|
|
25688
|
-
formats: array(string()).readonly(),
|
|
25689
|
-
sessionCount: number(),
|
|
25690
|
-
shm: CameraDecoderShmSchema
|
|
25691
|
-
});
|
|
25452
|
+
/**
|
|
25453
|
+
* Decoder block — WHERE decode runs (co-located with the detection node by
|
|
25454
|
+
* construction); null when the camera has no detection node. It carries no
|
|
25455
|
+
* frame counter: the shared-memory plane whose counters it used to serve is
|
|
25456
|
+
* gone, and those fields read 0 forever. Whether frames actually flow is read
|
|
25457
|
+
* from `detection.actualFps` (frames delivered to and processed by the
|
|
25458
|
+
* detector), never from a counter nothing feeds.
|
|
25459
|
+
*/
|
|
25460
|
+
var CameraDecoderStatusSchema = object({ nodeId: string() });
|
|
25692
25461
|
/** Motion block — null when motion detection is not active for this device. */
|
|
25693
25462
|
var CameraMotionStatusSchema = object({
|
|
25694
25463
|
enabled: boolean(),
|
|
@@ -26141,25 +25910,7 @@ method(object({
|
|
|
26141
25910
|
}), method(_void(), DiskReconcileJobSchema, {
|
|
26142
25911
|
kind: "mutation",
|
|
26143
25912
|
auth: "admin"
|
|
26144
|
-
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" })
|
|
26145
|
-
name: string(),
|
|
26146
|
-
description: string().optional(),
|
|
26147
|
-
config: CameraPipelineConfigSchema
|
|
26148
|
-
}), PipelineTemplateSchema, {
|
|
26149
|
-
kind: "mutation",
|
|
26150
|
-
auth: "admin"
|
|
26151
|
-
}), method(object({
|
|
26152
|
-
id: string(),
|
|
26153
|
-
name: string().optional(),
|
|
26154
|
-
description: string().optional(),
|
|
26155
|
-
config: CameraPipelineConfigSchema.optional()
|
|
26156
|
-
}), PipelineTemplateSchema, {
|
|
26157
|
-
kind: "mutation",
|
|
26158
|
-
auth: "admin"
|
|
26159
|
-
}), method(object({ id: string() }), object({ success: literal(true) }), {
|
|
26160
|
-
kind: "mutation",
|
|
26161
|
-
auth: "admin"
|
|
26162
|
-
});
|
|
25913
|
+
}), method(_void(), DiskReconcileJobSchema, { auth: "admin" });
|
|
26163
25914
|
/**
|
|
26164
25915
|
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
26165
25916
|
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
@@ -28379,8 +28130,6 @@ var WebrtcStreamChoiceSchema = object({
|
|
|
28379
28130
|
]).nullable(),
|
|
28380
28131
|
/** Input FPS from the camera (null for adaptive). */
|
|
28381
28132
|
inputFps: number().nullable(),
|
|
28382
|
-
/** Decoded FPS (null for adaptive). */
|
|
28383
|
-
decodeFps: number().nullable(),
|
|
28384
28133
|
/** Bitrate in kbps (null for adaptive). */
|
|
28385
28134
|
bitrateKbps: number().nullable()
|
|
28386
28135
|
});
|
|
@@ -28959,6 +28708,59 @@ var AddonAutoUpdateSchema = ChannelWithInheritSchema;
|
|
|
28959
28708
|
var RestartAddonResultSchema = unknown();
|
|
28960
28709
|
var InstallPackageResultSchema = unknown();
|
|
28961
28710
|
var ReloadPackagesResultSchema = unknown();
|
|
28711
|
+
/**
|
|
28712
|
+
* What an uninstall did on ONE node.
|
|
28713
|
+
* - `uninstalled` — removed: runner(s) stopped, caps gone, code deleted.
|
|
28714
|
+
* - `not-installed` — the node did not have it (nothing to do).
|
|
28715
|
+
* - `refused` — protected / bootstrap package; nothing touched.
|
|
28716
|
+
* - `failed` — attempted and did not complete; `error` says why.
|
|
28717
|
+
* - `pending-reconnect` — the node is OFFLINE: its record was pruned so the
|
|
28718
|
+
* back-fill never returns the package, and the stale-addon sweep removes the
|
|
28719
|
+
* copy when the node registers again (only once the hub no longer has it).
|
|
28720
|
+
*/
|
|
28721
|
+
var UninstallNodeOutcomeSchema = _enum([
|
|
28722
|
+
"uninstalled",
|
|
28723
|
+
"not-installed",
|
|
28724
|
+
"refused",
|
|
28725
|
+
"failed",
|
|
28726
|
+
"pending-reconnect"
|
|
28727
|
+
]);
|
|
28728
|
+
var UninstallNodeResultSchema = object({
|
|
28729
|
+
nodeId: string(),
|
|
28730
|
+
outcome: UninstallNodeOutcomeSchema,
|
|
28731
|
+
error: string().optional(),
|
|
28732
|
+
addonIds: array(string()).readonly(),
|
|
28733
|
+
runnersStopped: array(string()).readonly(),
|
|
28734
|
+
warnings: array(string()).readonly()
|
|
28735
|
+
});
|
|
28736
|
+
var UninstallPackageResultSchema = object({
|
|
28737
|
+
/** Every targeted node ended `uninstalled`, `not-installed` or `pending-reconnect`. */
|
|
28738
|
+
success: boolean(),
|
|
28739
|
+
packageName: string(),
|
|
28740
|
+
results: array(UninstallNodeResultSchema).readonly()
|
|
28741
|
+
});
|
|
28742
|
+
/**
|
|
28743
|
+
* `unreachable` lists online agents whose status read FAILED — absence from
|
|
28744
|
+
* `installations` is only "not installed" for a node that answered (D315).
|
|
28745
|
+
*/
|
|
28746
|
+
var PackageInstallationsSchema = object({
|
|
28747
|
+
installations: array(object({
|
|
28748
|
+
packageName: string(),
|
|
28749
|
+
nodeId: string(),
|
|
28750
|
+
nodeName: string(),
|
|
28751
|
+
isHub: boolean(),
|
|
28752
|
+
isOnline: boolean(),
|
|
28753
|
+
version: string().nullable(),
|
|
28754
|
+
addonIds: array(string()).readonly(),
|
|
28755
|
+
source: _enum(["live", "recorded"]),
|
|
28756
|
+
/** The hub installs this package too. `false` on an agent row = an orphan. */
|
|
28757
|
+
onHub: boolean()
|
|
28758
|
+
})).readonly(),
|
|
28759
|
+
unreachable: array(object({
|
|
28760
|
+
nodeId: string(),
|
|
28761
|
+
error: string()
|
|
28762
|
+
})).readonly()
|
|
28763
|
+
});
|
|
28962
28764
|
var BulkUpdateItemStatusSchema = _enum([
|
|
28963
28765
|
"queued",
|
|
28964
28766
|
"updating",
|
|
@@ -29041,10 +28843,14 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
|
|
|
29041
28843
|
}), method(object({ packageName: string() }), InstallPackageResultSchema, {
|
|
29042
28844
|
kind: "mutation",
|
|
29043
28845
|
auth: "admin"
|
|
29044
|
-
}), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({
|
|
28846
|
+
}), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({
|
|
28847
|
+
packageName: string().min(1),
|
|
28848
|
+
nodeId: string().optional(),
|
|
28849
|
+
everywhere: boolean().optional()
|
|
28850
|
+
}), UninstallPackageResultSchema, {
|
|
29045
28851
|
kind: "mutation",
|
|
29046
28852
|
auth: "admin"
|
|
29047
|
-
}), method(_void(), ReloadPackagesResultSchema, {
|
|
28853
|
+
}), method(object({ packageName: string().optional() }), PackageInstallationsSchema, { auth: "admin" }), method(_void(), ReloadPackagesResultSchema, {
|
|
29048
28854
|
kind: "mutation",
|
|
29049
28855
|
auth: "admin"
|
|
29050
28856
|
}), method(object({ query: string().optional() }), array(SearchResultSchema)), method(object({ nodeId: string().optional() }), array(PackageUpdateSchema).readonly(), { auth: "admin" }), method(object({
|
|
@@ -37333,6 +37139,12 @@ Object.freeze({
|
|
|
37333
37139
|
addonId: null,
|
|
37334
37140
|
access: "view"
|
|
37335
37141
|
},
|
|
37142
|
+
"addons.listInstallations": {
|
|
37143
|
+
capName: "addons",
|
|
37144
|
+
capScope: "system",
|
|
37145
|
+
addonId: null,
|
|
37146
|
+
access: "view"
|
|
37147
|
+
},
|
|
37336
37148
|
"addons.listJobs": {
|
|
37337
37149
|
capName: "addons",
|
|
37338
37150
|
capScope: "system",
|
|
@@ -38515,90 +38327,18 @@ Object.freeze({
|
|
|
38515
38327
|
addonId: null,
|
|
38516
38328
|
access: "create"
|
|
38517
38329
|
},
|
|
38518
|
-
"decoder.createSession": {
|
|
38519
|
-
capName: "decoder",
|
|
38520
|
-
capScope: "system",
|
|
38521
|
-
addonId: null,
|
|
38522
|
-
access: "view"
|
|
38523
|
-
},
|
|
38524
|
-
"decoder.destroySession": {
|
|
38525
|
-
capName: "decoder",
|
|
38526
|
-
capScope: "system",
|
|
38527
|
-
addonId: null,
|
|
38528
|
-
access: "delete"
|
|
38529
|
-
},
|
|
38530
|
-
"decoder.getFrame": {
|
|
38531
|
-
capName: "decoder",
|
|
38532
|
-
capScope: "system",
|
|
38533
|
-
addonId: null,
|
|
38534
|
-
access: "view"
|
|
38535
|
-
},
|
|
38536
38330
|
"decoder.getInfo": {
|
|
38537
38331
|
capName: "decoder",
|
|
38538
38332
|
capScope: "system",
|
|
38539
38333
|
addonId: null,
|
|
38540
38334
|
access: "view"
|
|
38541
38335
|
},
|
|
38542
|
-
"decoder.getShmStats": {
|
|
38543
|
-
capName: "decoder",
|
|
38544
|
-
capScope: "system",
|
|
38545
|
-
addonId: null,
|
|
38546
|
-
access: "view"
|
|
38547
|
-
},
|
|
38548
|
-
"decoder.getStats": {
|
|
38549
|
-
capName: "decoder",
|
|
38550
|
-
capScope: "system",
|
|
38551
|
-
addonId: null,
|
|
38552
|
-
access: "view"
|
|
38553
|
-
},
|
|
38554
|
-
"decoder.listActiveSessions": {
|
|
38555
|
-
capName: "decoder",
|
|
38556
|
-
capScope: "system",
|
|
38557
|
-
addonId: null,
|
|
38558
|
-
access: "view"
|
|
38559
|
-
},
|
|
38560
|
-
"decoder.openStream": {
|
|
38561
|
-
capName: "decoder",
|
|
38562
|
-
capScope: "system",
|
|
38563
|
-
addonId: null,
|
|
38564
|
-
access: "view"
|
|
38565
|
-
},
|
|
38566
|
-
"decoder.pullFrames": {
|
|
38567
|
-
capName: "decoder",
|
|
38568
|
-
capScope: "system",
|
|
38569
|
-
addonId: null,
|
|
38570
|
-
access: "view"
|
|
38571
|
-
},
|
|
38572
|
-
"decoder.pullHandles": {
|
|
38573
|
-
capName: "decoder",
|
|
38574
|
-
capScope: "system",
|
|
38575
|
-
addonId: null,
|
|
38576
|
-
access: "view"
|
|
38577
|
-
},
|
|
38578
|
-
"decoder.pushPacket": {
|
|
38579
|
-
capName: "decoder",
|
|
38580
|
-
capScope: "system",
|
|
38581
|
-
addonId: null,
|
|
38582
|
-
access: "view"
|
|
38583
|
-
},
|
|
38584
38336
|
"decoder.reprobeHwaccel": {
|
|
38585
38337
|
capName: "decoder",
|
|
38586
38338
|
capScope: "system",
|
|
38587
38339
|
addonId: null,
|
|
38588
38340
|
access: "create"
|
|
38589
38341
|
},
|
|
38590
|
-
"decoder.supportsCodec": {
|
|
38591
|
-
capName: "decoder",
|
|
38592
|
-
capScope: "system",
|
|
38593
|
-
addonId: null,
|
|
38594
|
-
access: "view"
|
|
38595
|
-
},
|
|
38596
|
-
"decoder.updateConfig": {
|
|
38597
|
-
capName: "decoder",
|
|
38598
|
-
capScope: "system",
|
|
38599
|
-
addonId: null,
|
|
38600
|
-
access: "view"
|
|
38601
|
-
},
|
|
38602
38342
|
"detectionPipeline.applyDeviceSettingsPatch": {
|
|
38603
38343
|
capName: "detection-pipeline",
|
|
38604
38344
|
capScope: "device",
|
|
@@ -41689,12 +41429,6 @@ Object.freeze({
|
|
|
41689
41429
|
addonId: null,
|
|
41690
41430
|
access: "delete"
|
|
41691
41431
|
},
|
|
41692
|
-
"pipelineExecutor.deleteTemplate": {
|
|
41693
|
-
capName: "pipeline-executor",
|
|
41694
|
-
capScope: "system",
|
|
41695
|
-
addonId: null,
|
|
41696
|
-
access: "delete"
|
|
41697
|
-
},
|
|
41698
41432
|
"pipelineExecutor.downloadModel": {
|
|
41699
41433
|
capName: "pipeline-executor",
|
|
41700
41434
|
capScope: "system",
|
|
@@ -41833,12 +41567,6 @@ Object.freeze({
|
|
|
41833
41567
|
addonId: null,
|
|
41834
41568
|
access: "view"
|
|
41835
41569
|
},
|
|
41836
|
-
"pipelineExecutor.listTemplates": {
|
|
41837
|
-
capName: "pipeline-executor",
|
|
41838
|
-
capScope: "system",
|
|
41839
|
-
addonId: null,
|
|
41840
|
-
access: "view"
|
|
41841
|
-
},
|
|
41842
41570
|
"pipelineExecutor.rearmInferenceDevice": {
|
|
41843
41571
|
capName: "pipeline-executor",
|
|
41844
41572
|
capScope: "system",
|
|
@@ -41863,12 +41591,6 @@ Object.freeze({
|
|
|
41863
41591
|
addonId: null,
|
|
41864
41592
|
access: "create"
|
|
41865
41593
|
},
|
|
41866
|
-
"pipelineExecutor.saveTemplate": {
|
|
41867
|
-
capName: "pipeline-executor",
|
|
41868
|
-
capScope: "system",
|
|
41869
|
-
addonId: null,
|
|
41870
|
-
access: "create"
|
|
41871
|
-
},
|
|
41872
41594
|
"pipelineExecutor.setVideoPipelineSteps": {
|
|
41873
41595
|
capName: "pipeline-executor",
|
|
41874
41596
|
capScope: "system",
|
|
@@ -41887,12 +41609,6 @@ Object.freeze({
|
|
|
41887
41609
|
addonId: null,
|
|
41888
41610
|
access: "create"
|
|
41889
41611
|
},
|
|
41890
|
-
"pipelineExecutor.updateTemplate": {
|
|
41891
|
-
capName: "pipeline-executor",
|
|
41892
|
-
capScope: "system",
|
|
41893
|
-
addonId: null,
|
|
41894
|
-
access: "create"
|
|
41895
|
-
},
|
|
41896
41612
|
"pipelineExecutor.validatePipeline": {
|
|
41897
41613
|
capName: "pipeline-executor",
|
|
41898
41614
|
capScope: "system",
|
|
@@ -41923,12 +41639,6 @@ Object.freeze({
|
|
|
41923
41639
|
addonId: null,
|
|
41924
41640
|
access: "create"
|
|
41925
41641
|
},
|
|
41926
|
-
"pipelineOrchestrator.deleteTemplate": {
|
|
41927
|
-
capName: "pipeline-orchestrator",
|
|
41928
|
-
capScope: "system",
|
|
41929
|
-
addonId: null,
|
|
41930
|
-
access: "delete"
|
|
41931
|
-
},
|
|
41932
41642
|
"pipelineOrchestrator.getAgentLoad": {
|
|
41933
41643
|
capName: "pipeline-orchestrator",
|
|
41934
41644
|
capScope: "system",
|
|
@@ -42079,12 +41789,6 @@ Object.freeze({
|
|
|
42079
41789
|
addonId: null,
|
|
42080
41790
|
access: "view"
|
|
42081
41791
|
},
|
|
42082
|
-
"pipelineOrchestrator.listTemplates": {
|
|
42083
|
-
capName: "pipeline-orchestrator",
|
|
42084
|
-
capScope: "system",
|
|
42085
|
-
addonId: null,
|
|
42086
|
-
access: "view"
|
|
42087
|
-
},
|
|
42088
41792
|
"pipelineOrchestrator.pauseForStorageMigration": {
|
|
42089
41793
|
capName: "pipeline-orchestrator",
|
|
42090
41794
|
capScope: "system",
|
|
@@ -42139,12 +41843,6 @@ Object.freeze({
|
|
|
42139
41843
|
addonId: null,
|
|
42140
41844
|
access: "create"
|
|
42141
41845
|
},
|
|
42142
|
-
"pipelineOrchestrator.saveTemplate": {
|
|
42143
|
-
capName: "pipeline-orchestrator",
|
|
42144
|
-
capScope: "system",
|
|
42145
|
-
addonId: null,
|
|
42146
|
-
access: "create"
|
|
42147
|
-
},
|
|
42148
41846
|
"pipelineOrchestrator.setAgentCapabilities": {
|
|
42149
41847
|
capName: "pipeline-orchestrator",
|
|
42150
41848
|
capScope: "system",
|
|
@@ -42253,12 +41951,6 @@ Object.freeze({
|
|
|
42253
41951
|
addonId: null,
|
|
42254
41952
|
access: "create"
|
|
42255
41953
|
},
|
|
42256
|
-
"pipelineOrchestrator.updateTemplate": {
|
|
42257
|
-
capName: "pipeline-orchestrator",
|
|
42258
|
-
capScope: "system",
|
|
42259
|
-
addonId: null,
|
|
42260
|
-
access: "create"
|
|
42261
|
-
},
|
|
42262
41954
|
"pipelineRunner.attachCamera": {
|
|
42263
41955
|
capName: "pipeline-runner",
|
|
42264
41956
|
capScope: "system",
|
|
@@ -43693,12 +43385,6 @@ Object.freeze({
|
|
|
43693
43385
|
addonId: null,
|
|
43694
43386
|
access: "view"
|
|
43695
43387
|
},
|
|
43696
|
-
"streamBroker.pullFrameHandles": {
|
|
43697
|
-
capName: "stream-broker",
|
|
43698
|
-
capScope: "system",
|
|
43699
|
-
addonId: null,
|
|
43700
|
-
access: "view"
|
|
43701
|
-
},
|
|
43702
43388
|
"streamBroker.regenerateRtspToken": {
|
|
43703
43389
|
capName: "stream-broker",
|
|
43704
43390
|
capScope: "system",
|
|
@@ -43765,12 +43451,6 @@ Object.freeze({
|
|
|
43765
43451
|
addonId: null,
|
|
43766
43452
|
access: "create"
|
|
43767
43453
|
},
|
|
43768
|
-
"streamBroker.subscribeFrames": {
|
|
43769
|
-
capName: "stream-broker",
|
|
43770
|
-
capScope: "system",
|
|
43771
|
-
addonId: null,
|
|
43772
|
-
access: "create"
|
|
43773
|
-
},
|
|
43774
43454
|
"streamBroker.unassignProfile": {
|
|
43775
43455
|
capName: "stream-broker",
|
|
43776
43456
|
capScope: "system",
|
|
@@ -43783,12 +43463,6 @@ Object.freeze({
|
|
|
43783
43463
|
addonId: null,
|
|
43784
43464
|
access: "create"
|
|
43785
43465
|
},
|
|
43786
|
-
"streamBroker.unsubscribeFrames": {
|
|
43787
|
-
capName: "stream-broker",
|
|
43788
|
-
capScope: "system",
|
|
43789
|
-
addonId: null,
|
|
43790
|
-
access: "create"
|
|
43791
|
-
},
|
|
43792
43466
|
"streamCatalog.getCatalog": {
|
|
43793
43467
|
capName: "stream-catalog",
|
|
43794
43468
|
capScope: "device",
|
|
@@ -46302,11 +45976,6 @@ Object.freeze({
|
|
|
46302
45976
|
form: "single",
|
|
46303
45977
|
optional: false
|
|
46304
45978
|
}],
|
|
46305
|
-
"decoder.createSession": [{
|
|
46306
|
-
name: "deviceId",
|
|
46307
|
-
form: "single",
|
|
46308
|
-
optional: true
|
|
46309
|
-
}],
|
|
46310
45979
|
"detectionPipeline.applyDeviceSettingsPatch": [{
|
|
46311
45980
|
name: "deviceId",
|
|
46312
45981
|
form: "single",
|
|
@@ -50447,24 +50116,6 @@ var CAMERA_STREAM_CONTROLLER = {
|
|
|
50447
50116
|
audioCodecs: ["AAC"]
|
|
50448
50117
|
}]
|
|
50449
50118
|
};
|
|
50450
|
-
/**
|
|
50451
|
-
* `Alexa.EndpointHealth` — REQUIRED on a sensor endpoint (alexa-endpointhealth;
|
|
50452
|
-
* alexa-motionsensor: "Must also implement `Alexa.EndpointHealth`"), and every
|
|
50453
|
-
* camera endpoint may carry `Alexa.MotionSensor`. Declared on every camera so
|
|
50454
|
-
* Alexa can tell an offline camera from a broken one: `connectivity` comes
|
|
50455
|
-
* from the `device-status` cap in ReportState and is pushed as a ChangeReport
|
|
50456
|
-
* on `DeviceOnline` / `DeviceOffline` by the Event Gateway.
|
|
50457
|
-
*/
|
|
50458
|
-
var ENDPOINT_HEALTH = {
|
|
50459
|
-
type: "AlexaInterface",
|
|
50460
|
-
interface: "Alexa.EndpointHealth",
|
|
50461
|
-
version: "3",
|
|
50462
|
-
properties: {
|
|
50463
|
-
supported: [{ name: "connectivity" }],
|
|
50464
|
-
proactivelyReported: true,
|
|
50465
|
-
retrievable: true
|
|
50466
|
-
}
|
|
50467
|
-
};
|
|
50468
50119
|
var DOORBELL_EVENT_SOURCE = {
|
|
50469
50120
|
type: "AlexaInterface",
|
|
50470
50121
|
interface: "Alexa.DoorbellEventSource",
|
|
@@ -50627,6 +50278,27 @@ var PTZ_TILT_MODE_CONTROLLER = ptzDirectionalModeController("ptz.tilt", "Tilt",
|
|
|
50627
50278
|
label: "Down"
|
|
50628
50279
|
}
|
|
50629
50280
|
]);
|
|
50281
|
+
/** Amazon (alexa-modecontroller): "You must include a minimum of two mode
|
|
50282
|
+
* objects." One preset made the camera's whole AddOrUpdateReport fail
|
|
50283
|
+
* schema validation, and Discover dropped the camera. */
|
|
50284
|
+
var MIN_MODE_CONTROLLER_MODES = 2;
|
|
50285
|
+
/**
|
|
50286
|
+
* Preset names as distinct mode values. Two presets with the same name (the
|
|
50287
|
+
* camera allows it: `Stanza`, `Stanza`; `CamStack Home` ×3) produced two
|
|
50288
|
+
* identical modes, and Alexa rejected the capability — "Invalid capability
|
|
50289
|
+
* received." — and with it every endpoint of the camera. First wins,
|
|
50290
|
+
* case-insensitively: the SetMode handler resolves a value to the first
|
|
50291
|
+
* preset of that name, which is the one kept.
|
|
50292
|
+
*/
|
|
50293
|
+
function distinctPresetNames(names) {
|
|
50294
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50295
|
+
return names.filter((name) => {
|
|
50296
|
+
const key = name.toLowerCase();
|
|
50297
|
+
if (seen.has(key)) return false;
|
|
50298
|
+
seen.add(key);
|
|
50299
|
+
return true;
|
|
50300
|
+
});
|
|
50301
|
+
}
|
|
50630
50302
|
function ptzPresetModeController(presetNames) {
|
|
50631
50303
|
return {
|
|
50632
50304
|
type: "AlexaInterface",
|
|
@@ -50666,13 +50338,13 @@ function buildParentCameraEndpoint(input) {
|
|
|
50666
50338
|
const capabilities = [
|
|
50667
50339
|
ALEXA_BASE_CAPABILITY,
|
|
50668
50340
|
CAMERA_STREAM_CONTROLLER,
|
|
50669
|
-
rtcSessionController(input.hasIntercom)
|
|
50670
|
-
ENDPOINT_HEALTH
|
|
50341
|
+
rtcSessionController(input.hasIntercom)
|
|
50671
50342
|
];
|
|
50672
50343
|
if (input.isDoorbell) capabilities.push(DOORBELL_EVENT_SOURCE);
|
|
50673
50344
|
if (input.hasMotion) capabilities.push(MOTION_SENSOR);
|
|
50674
50345
|
if (input.hasBattery) capabilities.push(BATTERY_LEVEL_SENSOR);
|
|
50675
|
-
|
|
50346
|
+
const presetNames = distinctPresetNames(input.ptzPresetNames);
|
|
50347
|
+
if (presetNames.length >= MIN_MODE_CONTROLLER_MODES) capabilities.push(ptzPresetModeController(presetNames));
|
|
50676
50348
|
if (input.hasPtz) {
|
|
50677
50349
|
capabilities.push(PTZ_PAN_MODE_CONTROLLER);
|
|
50678
50350
|
capabilities.push(PTZ_TILT_MODE_CONTROLLER);
|
|
@@ -50811,6 +50483,12 @@ function buildAlarmPanelEndpoint(input) {
|
|
|
50811
50483
|
};
|
|
50812
50484
|
}
|
|
50813
50485
|
//#endregion
|
|
50486
|
+
//#region src/handlers/ptz-preset-recallable.ts
|
|
50487
|
+
var RECALLABLE_FUNCTIONS = new Set(["home"]);
|
|
50488
|
+
function isAlexaRecallablePreset(preset) {
|
|
50489
|
+
return preset.fn === null || RECALLABLE_FUNCTIONS.has(preset.fn);
|
|
50490
|
+
}
|
|
50491
|
+
//#endregion
|
|
50814
50492
|
//#region src/handlers/discovery.ts
|
|
50815
50493
|
var discoveryPayloadSchema = DiscoveryDirectiveSchema.shape.payload;
|
|
50816
50494
|
/** Devices built at once in `handleDiscovery` — latency-bound tRPC reads, so
|
|
@@ -50998,7 +50676,7 @@ async function loadBoundDeviceInfo(device, api) {
|
|
|
50998
50676
|
};
|
|
50999
50677
|
}
|
|
51000
50678
|
async function fetchPtzPresetNames(deviceId, api) {
|
|
51001
|
-
return (await api.ptz.getPresets.query({ deviceId })).map((p) => p.name).filter((n) => n.length > 0);
|
|
50679
|
+
return (await api.ptz.getPresets.query({ deviceId })).filter(isAlexaRecallablePreset).map((p) => p.name).filter((n) => n.length > 0);
|
|
51002
50680
|
}
|
|
51003
50681
|
function classifyChildKind(deviceType, role) {
|
|
51004
50682
|
if (role === "floodlight" || role === "spotlight" || role === "nightvision") return "light";
|
|
@@ -51398,8 +51076,8 @@ async function handleSetMode(header, endpointRaw, payloadRaw, deps, _callerIdent
|
|
|
51398
51076
|
if (!mode.startsWith(PTZ_PRESET_MODE_PREFIX)) return errorEnvelope(header, "INVALID_DIRECTIVE", `mode '${mode}' is not a ptz.preset mode`);
|
|
51399
51077
|
const presetName = mode.slice(11);
|
|
51400
51078
|
if (presetName.length === 0) return errorEnvelope(header, "INVALID_DIRECTIVE", "preset name missing after prefix");
|
|
51401
|
-
const preset = (await api.ptz.getPresets.query({ deviceId: parsedId.deviceId })).find((p) => p.name === presetName);
|
|
51402
|
-
if (!preset) return errorEnvelope(header, "INVALID_DIRECTIVE", `preset '${presetName}' not
|
|
51079
|
+
const preset = (await api.ptz.getPresets.query({ deviceId: parsedId.deviceId })).find((p) => p.name === presetName && isAlexaRecallablePreset(p));
|
|
51080
|
+
if (!preset) return errorEnvelope(header, "INVALID_DIRECTIVE", `preset '${presetName}' is not a recallable preset on device ${parsedId.deviceId}`);
|
|
51403
51081
|
await api.ptz.goToPreset.mutate({
|
|
51404
51082
|
deviceId: parsedId.deviceId,
|
|
51405
51083
|
presetId: preset.id
|
|
@@ -51491,20 +51169,6 @@ async function collectCameraProperties(api, deviceId, properties, timeOfSample,
|
|
|
51491
51169
|
timeOfSample,
|
|
51492
51170
|
uncertaintyInMilliseconds: 0
|
|
51493
51171
|
});
|
|
51494
|
-
const online = boolField(await api.deviceStatus.getStatus.query({ deviceId }).catch((err) => {
|
|
51495
|
-
logger.warn("alexa report-state: deviceStatus.getStatus failed — connectivity omitted", {
|
|
51496
|
-
tags: { deviceId },
|
|
51497
|
-
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
51498
|
-
});
|
|
51499
|
-
return null;
|
|
51500
|
-
}), "online");
|
|
51501
|
-
if (online !== null) properties.push({
|
|
51502
|
-
namespace: "Alexa.EndpointHealth",
|
|
51503
|
-
name: "connectivity",
|
|
51504
|
-
value: { value: online ? "OK" : "UNREACHABLE" },
|
|
51505
|
-
timeOfSample,
|
|
51506
|
-
uncertaintyInMilliseconds: 0
|
|
51507
|
-
});
|
|
51508
51172
|
const detected = boolField(await api.motion.getStatus.query({ deviceId }).catch((err) => {
|
|
51509
51173
|
logger.info("alexa report-state: motion.getStatus skipped", { meta: {
|
|
51510
51174
|
deviceId,
|
|
@@ -53461,7 +53125,7 @@ function buildAlexaOauthIntegration(publicHubUrl) {
|
|
|
53461
53125
|
* client id and SECRET, on the theory that a per-account refresh token was the
|
|
53462
53126
|
* real gate. The package is public on npm, so that secret was published with
|
|
53463
53127
|
* every version and has to be rotated. Since D753 the secret lives only in the
|
|
53464
|
-
* skill's Lambda (
|
|
53128
|
+
* skill's Lambda (SSM Parameter Store SecureString, D761); the hub gets short-lived Event Gateway
|
|
53465
53129
|
* tokens from the Lambda's broker (`broker-client.ts`) with a per-link
|
|
53466
53130
|
* credential. `scripts/check-no-client-secrets.ts` keeps it that way.
|
|
53467
53131
|
*
|
|
@@ -54492,7 +54156,7 @@ var ExportAlexaAddon = class extends BaseAddon {
|
|
|
54492
54156
|
content: [
|
|
54493
54157
|
"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).",
|
|
54494
54158
|
"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.",
|
|
54495
|
-
"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
|
|
54159
|
+
"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).",
|
|
54496
54160
|
"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."
|
|
54497
54161
|
].join("\n")
|
|
54498
54162
|
},
|
|
@@ -54559,7 +54223,7 @@ var ExportAlexaAddon = class extends BaseAddon {
|
|
|
54559
54223
|
key: "__custom-skill-info",
|
|
54560
54224
|
label: "Your skill Lambda",
|
|
54561
54225
|
variant: "info",
|
|
54562
|
-
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
|
|
54226
|
+
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."
|
|
54563
54227
|
}] : [{
|
|
54564
54228
|
type: "info",
|
|
54565
54229
|
key: "__public-skill-info",
|