@camstack/addon-pipeline 1.2.273 → 1.2.274

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.
Files changed (32) hide show
  1. package/dist/audio-analyzer/index.js +2 -2
  2. package/dist/audio-analyzer/index.mjs +2 -2
  3. package/dist/{default-detection-model-DCFaNnYd.mjs → default-detection-model-BXwE-Dvo.mjs} +1 -1
  4. package/dist/{default-detection-model-9Solpn0K.js → default-detection-model-CAWhHQo2.js} +1 -1
  5. package/dist/detection-pipeline/index.js +4 -4
  6. package/dist/detection-pipeline/index.mjs +4 -4
  7. package/dist/{dist-BRT-qKlE.mjs → dist-g5MfpiBh.mjs} +194 -98
  8. package/dist/{dist-DRDzfOnl.js → dist-k6Vu-AhZ.js} +217 -97
  9. package/dist/motion-wasm/index.js +1 -1
  10. package/dist/motion-wasm/index.mjs +1 -1
  11. package/dist/{node-BmTPPuIg.js → node--u_jUObS.js} +1 -1
  12. package/dist/{node-Dwu66ZR4.mjs → node-BXsHQH5h.mjs} +1 -1
  13. package/dist/pipeline-runner/index.js +3 -3
  14. package/dist/pipeline-runner/index.mjs +3 -3
  15. package/dist/{process-memory-BTwHfysZ.js → process-memory-DN7opum2.js} +1 -1
  16. package/dist/{process-memory-Cx4oDFz9.mjs → process-memory-Gl3EowL-.mjs} +1 -1
  17. package/dist/recorder/index.js +570 -2
  18. package/dist/recorder/index.mjs +570 -2
  19. package/dist/{segment-demux-js--ePyI476.js → segment-demux-js-DHX8o8pI.js} +1 -1
  20. package/dist/{segment-demux-js-BKvYCad_.mjs → segment-demux-js-sYP_jndp.mjs} +1 -1
  21. package/dist/stream-broker/_stub.js +2 -2
  22. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-shbmpL8E.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CEy8IryH.mjs} +2 -2
  23. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BlXyfeXU.mjs +26 -0
  24. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-C8RTK6nJ.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-MU3_q1MX.mjs} +1 -1
  25. package/dist/stream-broker/demux-worker-child.js +1 -1
  26. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  27. package/dist/stream-broker/{hostInit-CtVYKCNe.mjs → hostInit-UKNN4qes.mjs} +2 -2
  28. package/dist/stream-broker/index.js +3 -3
  29. package/dist/stream-broker/index.mjs +3 -3
  30. package/dist/stream-broker/remoteEntry.js +1 -1
  31. package/package.json +5 -1
  32. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-C_SEu7AC.mjs +0 -26
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-emK7D4bc.js");
6
- const require_dist = require("../dist-DRDzfOnl.js");
7
- const require_process_memory = require("../process-memory-BTwHfysZ.js");
6
+ const require_dist = require("../dist-k6Vu-AhZ.js");
7
+ const require_process_memory = require("../process-memory-DN7opum2.js");
8
8
  let node_fs = require("node:fs");
9
9
  node_fs = require_chunk.__toESM(node_fs);
10
10
  let node_path = require("node:path");
@@ -1,6 +1,6 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { $t as hydrateSchema, Jt as audioChunkBytesPerSample, Lt as errMsg, N as audioAnalysisCapability, Ot as resolvePoolMemoryPolicy, P as audioAnalyzerCapability, Qt as expandAudioChunkToF32le, Wt as BaseAddon, bn as EventCategory, n as AUDIO_BACKEND_CHOICES, ot as mapAudioLabelToMacro, rn as nodePin, s as DEFAULT_AUDIO_ANALYZER_CONFIG, w as PoolMemoryWatchdog, y as HF_BASE_URL } from "../dist-BRT-qKlE.mjs";
3
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-Cx4oDFz9.mjs";
2
+ import { E as PoolMemoryWatchdog, I as audioAnalysisCapability, Jt as BaseAddon, L as audioAnalyzerCapability, Qt as audioChunkBytesPerSample, Vt as errMsg, jt as resolvePoolMemoryPolicy, lt as mapAudioLabelToMacro, n as AUDIO_BACKEND_CHOICES, nn as expandAudioChunkToF32le, rn as hydrateSchema, s as DEFAULT_AUDIO_ANALYZER_CONFIG, sn as nodePin, wn as EventCategory, x as HF_BASE_URL } from "../dist-g5MfpiBh.mjs";
3
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-Gl3EowL-.mjs";
4
4
  import * as fs from "node:fs";
5
5
  import * as path$1 from "node:path";
6
6
  import { downloadFile } from "@camstack/system/addon-utils";
@@ -1,4 +1,4 @@
1
- import { F as audioKindId, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS, tt as hfModelUrl } from "./dist-BRT-qKlE.mjs";
1
+ import { R as audioKindId, a as COCO_80_LABELS, it as hfModelUrl, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-g5MfpiBh.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  //#region src/detection-pipeline/pipeline/landmark-precision-gate.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-DRDzfOnl.js");
1
+ const require_dist = require("./dist-k6Vu-AhZ.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  //#region src/detection-pipeline/pipeline/landmark-precision-gate.ts
4
4
  /**
@@ -3,11 +3,11 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-emK7D4bc.js");
6
- const require_dist = require("../dist-DRDzfOnl.js");
7
- const require_node = require("../node-BmTPPuIg.js");
8
- const require_default_detection_model = require("../default-detection-model-9Solpn0K.js");
6
+ const require_dist = require("../dist-k6Vu-AhZ.js");
7
+ const require_node = require("../node--u_jUObS.js");
8
+ const require_default_detection_model = require("../default-detection-model-CAWhHQo2.js");
9
9
  const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
10
- const require_process_memory = require("../process-memory-BTwHfysZ.js");
10
+ const require_process_memory = require("../process-memory-DN7opum2.js");
11
11
  let node_os = require("node:os");
12
12
  node_os = require_chunk.__toESM(node_os);
13
13
  let node_fs = require("node:fs");
@@ -1,9 +1,9 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { $t as hydrateSchema, At as runtimeDevices$1, Ft as supportedRuntimes$1, G as detectionPipelineCapability, J as enumerateInferenceDevices, Lt as errMsg, Ot as resolvePoolMemoryPolicy, Tt as resolveClusterStepModelId, V as defaultDeviceFor$1, Wt as BaseAddon, X as evaluateZoneRules, Yt as createEvent, bn as EventCategory, c as DEFAULT_CLUSTER_STEP_MODELS, gt as pickClusterStepSettings, hn as object, ht as pickClusterStepModels, in as parseJsonUnknown, it as loadContributionCapability, j as YAMNET_TO_MACRO, l as DEFAULT_CLUSTER_STEP_SETTINGS, ln as array, m as DEVICE_BACKEND_TO_FORMAT, nt as inferModelProvider, pt as overlayClusterStepSettings, rn as nodePin, sn as sleep, t as APPLE_SA_TO_MACRO, vn as string, w as PoolMemoryWatchdog, yn as union, yt as pipelineExecutorCapability } from "../dist-BRT-qKlE.mjs";
3
- import { s as readProcessCost } from "../node-Dwu66ZR4.mjs";
4
- import { a as localFrameRegistry, c as ALL_STEPS, d as getStepDefinition, f as resolveModelForFormat, l as getDefaultModelForFormat, n as resolveDefaultDetectionModel, p as landmarkPrecisionVerdict, r as macroGateVerdict, s as ALL_PIPELINE_STEPS, u as getStep } from "../default-detection-model-DCFaNnYd.mjs";
2
+ import { $ as evaluateZoneRules, $t as createEvent, Cn as union, E as PoolMemoryWatchdog, J as detectionPipelineCapability, Jt as BaseAddon, Nt as runtimeDevices$1, Ot as resolveClusterStepModelId, P as YAMNET_TO_MACRO, Rt as supportedRuntimes$1, Sn as string, St as pipelineExecutorCapability, Vt as errMsg, W as defaultDeviceFor$1, Z as enumerateInferenceDevices, at as inferModelProvider, c as DEFAULT_CLUSTER_STEP_MODELS, cn as parseJsonUnknown, dn as sleep, gt as overlayClusterStepSettings, jt as resolvePoolMemoryPolicy, l as DEFAULT_CLUSTER_STEP_SETTINGS, m as DEVICE_BACKEND_TO_FORMAT, pn as array, rn as hydrateSchema, sn as nodePin, st as loadContributionCapability, t as APPLE_SA_TO_MACRO, vt as pickClusterStepModels, wn as EventCategory, yn as object, yt as pickClusterStepSettings } from "../dist-g5MfpiBh.mjs";
3
+ import { s as readProcessCost } from "../node-BXsHQH5h.mjs";
4
+ import { a as localFrameRegistry, c as ALL_STEPS, d as getStepDefinition, f as resolveModelForFormat, l as getDefaultModelForFormat, n as resolveDefaultDetectionModel, p as landmarkPrecisionVerdict, r as macroGateVerdict, s as ALL_PIPELINE_STEPS, u as getStep } from "../default-detection-model-BXwE-Dvo.mjs";
5
5
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
6
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-Cx4oDFz9.mjs";
6
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-Gl3EowL-.mjs";
7
7
  import * as os from "node:os";
8
8
  import * as fs from "node:fs";
9
9
  import * as path$1 from "node:path";
@@ -5360,7 +5360,7 @@ var ZodIssueCode = {
5360
5360
  var ZodFirstPartyTypeKind;
5361
5361
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5362
5362
  //#endregion
5363
- //#region ../types/dist/sleep-CopaBJss.mjs
5363
+ //#region ../types/dist/sleep-CaB_hL5g.mjs
5364
5364
  /**
5365
5365
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5366
5366
  * window to float samples (D455).
@@ -5592,12 +5592,6 @@ Object.fromEntries([
5592
5592
  icon: "circle-dot",
5593
5593
  order: 40
5594
5594
  },
5595
- {
5596
- id: "clips",
5597
- label: "Clips",
5598
- icon: "clapperboard",
5599
- order: 41
5600
- },
5601
5595
  {
5602
5596
  id: "engine",
5603
5597
  label: "Inference Engine",
@@ -8347,6 +8341,8 @@ var EVENT_OWNER_TYPES = [
8347
8341
  * nothing failing until a caller asked.
8348
8342
  */
8349
8343
  var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
8344
+ /** The same list as a Zod enum, for the cap input that carries it. */
8345
+ var MediaPresenceOwnerKindSchema = _enum([...EVENT_OWNER_TYPES, "track"]);
8350
8346
  new Set(EVENT_OWNER_TYPES);
8351
8347
  var EncodeProfileSchema = object({
8352
8348
  video: object({
@@ -9327,6 +9323,24 @@ var DetectionCatalogClassMapSchema = object({
9327
9323
  preserveOriginal: boolean()
9328
9324
  });
9329
9325
  /**
9326
+ * THE canonical event-clip pad: the time window a single-timestamp analytics
9327
+ * event expands to when joined with footage (clip window = `[timestamp - preMs,
9328
+ * timestamp + postMs]`). Matches the admin-ui clip window (−5s/+10s).
9329
+ *
9330
+ * Every consumer derives from this ONE constant so event↔footage boundaries
9331
+ * agree everywhere (C1): today that is the `videoclips` default provider
9332
+ * (addon-post-analysis), which pads its clip windows with it. The recorder used
9333
+ * to pad in-RAM playback markers with it too; those markers had no reader
9334
+ * anywhere in the repo and were deleted on 2026-08-29.
9335
+ *
9336
+ * NOTE: this is a UI/JOIN convention, NOT the `events`-band keep/discard gate —
9337
+ * that uses the per-device `preBufferSec`/`postBufferSec` config.
9338
+ */
9339
+ var EVENT_PAD_MS = {
9340
+ preMs: 5e3,
9341
+ postMs: 1e4
9342
+ };
9343
+ /**
9330
9344
  * Numeric day-of-week: 0 = Sunday … 6 = Saturday (matches `Date.getDay`).
9331
9345
  * Named `RecordingWeekday` to avoid collision with the string-union
9332
9346
  * `Weekday` exported from `interfaces/timezones.ts`.
@@ -9543,7 +9557,20 @@ function stripRetiredBandPreBufferSec(config) {
9543
9557
  strippedBands
9544
9558
  };
9545
9559
  }
9546
- DEFAULT_EVENTS_BAND_BUFFER_SEC.postBufferSec * 1e3;
9560
+ /**
9561
+ * Adjacent recorded ranges closer than this belong to the SAME videoclip visit.
9562
+ *
9563
+ * This is NOT the recorder calendar merge (`RANGE_MERGE_GAP_MS = 5s`). That
9564
+ * threshold is for the timeline bar, which must show exact holes — including
9565
+ * the ~8s GOP/keyframe rolls measured on events-mode cameras (dispensa 1438,
9566
+ * 2026-08-16). A videoclip is the events-mode keep-window (writer session),
9567
+ * whose idle bound is `postBufferSec`. Using that default (30s) glues those
9568
+ * intra-visit holes without joining visits hours apart.
9569
+ *
9570
+ * Segments stay the source of truth on disk (`startMs-durMs-bytes.m4s`); a
9571
+ * visit is derived, not a second copy of the files.
9572
+ */
9573
+ var VISIT_MERGE_GAP_MS = DEFAULT_EVENTS_BAND_BUFFER_SEC.postBufferSec * 1e3;
9547
9574
  /**
9548
9575
  * Per-device retention overrides. Every field is optional; an unset or `0`
9549
9576
  * value inherits the node-wide recorder default. Only footage-lifetime limits
@@ -16442,8 +16469,6 @@ method(object({
16442
16469
  deviceId: number(),
16443
16470
  capName: string(),
16444
16471
  wrapperAddonId: string(),
16445
- /** The `ClipSource.source` id to toggle. Absent = all of the addon's. */
16446
- sourceId: string().optional(),
16447
16472
  active: boolean()
16448
16473
  }), _void(), {
16449
16474
  kind: "mutation",
@@ -23935,7 +23960,11 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
23935
23960
  ownerType: EventOwnerTypeSchema,
23936
23961
  eventId: number().int(),
23937
23962
  deviceId: number()
23938
- }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
23963
+ }), array(MediaFileInfoSchema).readonly()), method(object({
23964
+ deviceId: number(),
23965
+ ownerKind: MediaPresenceOwnerKindSchema,
23966
+ ownerIds: array(string()).max(5e3)
23967
+ }), array(string()).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
23939
23968
  kind: "mutation",
23940
23969
  auth: "admin"
23941
23970
  }), method(RebuildObjectEmbeddingsInput, RebuildObjectEmbeddingsResultSchema, {
@@ -27163,6 +27192,18 @@ method(VectorDeclareIndexInputSchema, _void(), {
27163
27192
  kind: "mutation",
27164
27193
  auth: "admin"
27165
27194
  }), method(VectorStatsInputSchema, VectorStatsResultSchema, { auth: "admin" });
27195
+ _enum([
27196
+ "queue-full",
27197
+ "camera-backoff",
27198
+ "sleeping",
27199
+ "camera-refused",
27200
+ "no-keyframe",
27201
+ "no-catalog-row",
27202
+ "unsupported",
27203
+ "unknown-device",
27204
+ "uid-missing"
27205
+ ]);
27206
+ _enum(["deferred", "final"]);
27166
27207
  var ClipSchema = object({
27167
27208
  /** Opaque, provider-namespaced id. The default provider encodes the time
27168
27209
  * window so `getClipPlayback` is self-contained (no event re-query). */
@@ -27313,7 +27354,25 @@ var ClipSchema = object({
27313
27354
  */
27314
27355
  playable: boolean().optional(),
27315
27356
  /** Why {@link playable} is false, verbatim (`no-file-for-window`). */
27316
- unplayableReason: string().optional()
27357
+ unplayableReason: string().optional(),
27358
+ /**
27359
+ * This clip is STILL BEING WRITTEN, so {@link ClipSchema.timeRange}`.endMs`
27360
+ * is not its end.
27361
+ *
27362
+ * Absent — the common case — means the row is closed and its `endMs` is the
27363
+ * end of the recording. Present and `true` means the source told us the file
27364
+ * has no end yet, and the `endMs` we carry is whatever the camera's index
27365
+ * entry happened to hold: on a Reolink E1 Outdoor PoE (592, measured
27366
+ * 2026-09-20) the newest file `…_192927_000000_…_0.mp4` reported an `endTime`
27367
+ * of 19:29:56 and STILL reported it eight minutes later, while the file went
27368
+ * on growing. A surface that drew 29 s there was lying about a clip that
27369
+ * plays for minutes, on the one row the operator looks at first.
27370
+ *
27371
+ * `endMs` is deliberately still a number: it is the best bound anything has
27372
+ * for a mint window or a byte fetch, and every consumer already requires it.
27373
+ * This flag says what it is WORTH, and a duration is not drawn from it.
27374
+ */
27375
+ inProgress: boolean().optional()
27317
27376
  });
27318
27377
  var ClipPlaybackSchema = object({
27319
27378
  /**
@@ -27396,99 +27455,125 @@ var ClipSourceSchema = object({
27396
27455
  * alternative — a `native:reolink:* → provider-reolink` table inside the
27397
27456
  * widget — is a second authority on provider identity living in the one
27398
27457
  * package with no business knowing it, wrong the day a third source appears
27399
- * (D557). One addon may serve SEVERAL sources: `addon-provider-reolink`
27400
- * answers a hub child with both `native:reolink:onboard` and
27401
- * `native:reolink:hub`, which is why the per-device switch is keyed by
27402
- * SOURCE and not by this (D555).
27458
+ * (D557). One addon may serve SEVERAL sources, which is why the per-device
27459
+ * switch is keyed by SOURCE and not by this (D555) — `addon-provider-reolink`
27460
+ * served a hub child two of them until the two views were measured to be one
27461
+ * store read twice (D555) and then read ONE way (D565).
27403
27462
  *
27404
27463
  * Optional for version skew only. The collection dispatcher stamps it from
27405
27464
  * the registry, so a row that travelled through the fan-out carries the
27406
27465
  * authoritative id whatever the provider filled in.
27407
27466
  */
27408
27467
  addonId: string().optional(),
27409
- /**
27410
- * Which API this source resolved to FOR THIS CAMERA, when it has a choice.
27411
- *
27412
- * A source may cover one store through more than one surface — the Reolink
27413
- * provider reads a hub child through the parent's event log and a standalone
27414
- * through its own file list, because that is what each camera answers. The
27415
- * CHOICE is the provider's, made from what the camera is, and is never a row
27416
- * the operator has to understand; but it is REPORTED, because a source that
27417
- * silently reads a different API on two cameras and then behaves differently
27418
- * is the thing nobody can debug later. Absent when the source has only one
27419
- * way to read its store.
27420
- */
27421
- via: string().optional(),
27422
- availability: ClipSourceAvailabilitySchema,
27423
- /**
27424
- * The operator switched this source OFF for this camera.
27425
- *
27426
- * Deliberately NOT a member of {@link ClipSourceAvailabilitySchema}'s
27427
- * vocabulary. That enum models what the source CAN do — a sleeping camera, an
27428
- * unmounted card, an index that disagrees with its own calendar — and a
27429
- * switched-off source could answer perfectly well; the operator decided it
27430
- * should not. Folding the choice in is how `disabled` and `broken` stop being
27431
- * distinguishable, which is the D62 rule this repo has already paid for twice:
27432
- * an off switch is REPORTED off (`CameraStatus.switchedOff`, the same word),
27433
- * and disabled must never look like broken. It is also what lets every
27434
- * exhaustive consumer of the availability enum keep compiling.
27435
- *
27436
- * A switched-off source contributes NO clips (`listClips` never calls it) and
27437
- * its row carries no `catalogAsOf`: nothing confirms a catalog it is not
27438
- * allowed to serve, and a frozen age that can only grow draws a stalling
27439
- * source rather than an off switch.
27440
- *
27441
- * The row survives BECAUSE it is the control the operator switches the source
27442
- * back on from — D554 decision 4's rule ("a source that cannot answer
27443
- * produces a ROW, not an absence") applied to the one case D556 carved out of
27444
- * it, and D557's own kept property ("a source is never hidden, only its
27445
- * rows"). Absent means on.
27446
- *
27447
- * A provider never sets this — like {@link ClipSourceSchema.addonId} it is
27448
- * stamped by the collection dispatcher, which holds the registry's projection
27449
- * of the persisted authority (D556) and is the only place that knows it.
27450
- */
27451
- switchedOff: boolean().optional()
27468
+ availability: ClipSourceAvailabilitySchema
27452
27469
  });
27453
- DeviceType.Camera, method(object({
27454
- deviceId: number(),
27455
- since: number(),
27456
- until: number(),
27457
- limit: number().int().positive().optional(),
27458
- /**
27459
- * View filter over {@link ClipSourceSchema.source} values — the
27460
- * picker's selection, forwarded so a provider need not list what
27461
- * nobody is looking at. ABSENT means every source this camera has,
27462
- * which is the honest default for a surface whose whole point is that
27463
- * nothing is hidden (D554 3). A provider with one source ignores it.
27464
- */
27465
- sources: array(string()).optional()
27466
- }), array(ClipSchema).readonly(), {
27467
- kind: "query",
27468
- auth: "protected"
27469
- }), method(object({ deviceId: number() }), array(ClipSourceSchema).readonly(), {
27470
- kind: "query",
27471
- auth: "protected"
27472
- }), method(object({
27473
- deviceId: number(),
27474
- clipId: string(),
27470
+ var videoclipsCapability = {
27471
+ name: "videoclips",
27472
+ scope: "device",
27473
+ mode: "collection",
27474
+ kind: "wrapper",
27475
+ defaultActive: true,
27476
+ /** A clip is a window over a camera's footage — the cap is meaningless on a
27477
+ * sensor, a button or an event emitter, and the `defaultActive` auto-bind
27478
+ * reads this to decide which devices it may claim. */
27479
+ deviceTypes: [DeviceType.Camera],
27475
27480
  /**
27476
- * Which twin to serve, on the ONE quality scale the system already has
27477
- * (`CamProfileSchema`). `low | mid` → the sub file, `high` → the main
27478
- * twin; both ids are already on the row so this never re-searches the
27479
- * camera. Absent means the provider's own default (the sub file, which
27480
- * every source is measured to hold).
27481
- *
27482
- * `auto` is deliberately NOT accepted here: a stored file has no
27483
- * broker session, so the adaptive tier cannot be resolved for it. The
27484
- * viewer resolves `auto` to a profile the same way live does, before
27485
- * it calls (D549 15).
27486
- */
27487
- profile: CamProfileSchema.optional()
27488
- }), ClipPlaybackSchema, {
27489
- kind: "query",
27490
- auth: "protected"
27491
- });
27481
+ * The Clips section of a camera's device details is FRAMEWORK-DERIVED (D14):
27482
+ * the aggregator turns this declaration into the `type:'widget'` section and
27483
+ * `DeviceDetail.tsx` is never edited. `videoclips` is the first WRAPPER cap
27484
+ * to declare one — every previous `host/` widget cap is `deviceNative` — so
27485
+ * `device-config-widget-wrapped-binding.spec.ts` pins that a `kind:'wrapped'`
27486
+ * binding entry derives the same section a native one does.
27487
+ *
27488
+ * **It is a SECTION of the Recording tab, at the end of it — not a tab of
27489
+ * its own.** It shipped as a `clips` top-tab and the operator rejected the
27490
+ * placement: *"utilizzerei la stessa tab recordings, lì abbiamo già tutto il
27491
+ * necessario, una nuova sezione alla fine per le clips"*. The Recording tab
27492
+ * already holds the recorder's panel, the schedule bands and the unified
27493
+ * retention policy; footage the camera itself holds is the same question,
27494
+ * asked of a different store. `order: 100` puts it after all of them with
27495
+ * room left in front. The `clips` entry in `WELL_KNOWN_TABS` went with it —
27496
+ * a well-known id nobody declares is an invitation to mint the tab again.
27497
+ *
27498
+ * `topTab` stays: the browser owns a pane (a day's tiles, a source list and
27499
+ * a player) and the Config tab's inner bar has no room for one. The widget
27500
+ * itself is `host/clips-browser` in ui-library's `HOST_WIDGETS`, and because
27501
+ * the admin Recordings page renders every `location:'top-tab'` +
27502
+ * `tab:'recording'` section behind its camera picker
27503
+ * (`CameraRecordingSettingsSection`), this declaration lands the section on
27504
+ * BOTH surfaces with no second wiring.
27505
+ */
27506
+ deviceConfig: { ui: {
27507
+ kind: "widget",
27508
+ widgetId: "host/clips-browser",
27509
+ tab: "recording",
27510
+ topTab: true,
27511
+ label: "Clips",
27512
+ order: 100
27513
+ } },
27514
+ methods: {
27515
+ listClips: method(object({
27516
+ deviceId: number(),
27517
+ since: number(),
27518
+ until: number(),
27519
+ limit: number().int().positive().optional(),
27520
+ /**
27521
+ * WHICH provider to ask — the `addonId` a {@link ClipSourceSchema} row
27522
+ * carries, never a source id and never a list.
27523
+ *
27524
+ * Absent means the device's BOUND provider, which is CamStack on every
27525
+ * camera today because that is what `deviceManager.getBindings`
27526
+ * answers with. A provider the device is not bound to is refused by
27527
+ * name rather than answered by another one (D552's
27528
+ * `rejectUnresolvedAddonPin` rule).
27529
+ *
27530
+ * It replaced `sources?: string[]`, a VIEW filter over source ids that
27531
+ * assumed the answer was a fan-out over everything a camera has. The
27532
+ * operator settled otherwise on 2026-09-20 — *"il get videoclips
27533
+ * prendere un provider opzionale, di default va su camstack"*,
27534
+ * *"l'utilizzatore è uno solo"* — so the list is asked of one provider
27535
+ * at a time and there is nothing to filter out of it.
27536
+ */
27537
+ provider: string().optional()
27538
+ }), array(ClipSchema).readonly(), {
27539
+ kind: "query",
27540
+ auth: "protected"
27541
+ }),
27542
+ /**
27543
+ * The sources this camera has, WITH the reason any of them cannot answer.
27544
+ *
27545
+ * Asked separately from `listClips` because an empty clip list is
27546
+ * ambiguous and this is the only place the ambiguity is resolved: every
27547
+ * bound provider contributes its own rows, and a provider that could not
27548
+ * be reached at all still produces one row saying so. A surface that draws
27549
+ * "no clips" without reading this is drawing a guess.
27550
+ */
27551
+ listSources: method(object({ deviceId: number() }), array(ClipSourceSchema).readonly(), {
27552
+ kind: "query",
27553
+ auth: "protected"
27554
+ }),
27555
+ getClipPlayback: method(object({
27556
+ deviceId: number(),
27557
+ clipId: string(),
27558
+ /**
27559
+ * Which twin to serve, on the ONE quality scale the system already has
27560
+ * (`CamProfileSchema`). `low | mid` → the sub file, `high` → the main
27561
+ * twin; both ids are already on the row so this never re-searches the
27562
+ * camera. Absent means the provider's own default (the sub file, which
27563
+ * every source is measured to hold).
27564
+ *
27565
+ * `auto` is deliberately NOT accepted here: a stored file has no
27566
+ * broker session, so the adaptive tier cannot be resolved for it. The
27567
+ * viewer resolves `auto` to a profile the same way live does, before
27568
+ * it calls (D549 15).
27569
+ */
27570
+ profile: CamProfileSchema.optional()
27571
+ }), ClipPlaybackSchema, {
27572
+ kind: "query",
27573
+ auth: "protected"
27574
+ })
27575
+ }
27576
+ };
27492
27577
  /**
27493
27578
  * Optional client-side hints sent at session creation to help the provider
27494
27579
  * pick the best native source. All fields optional — a viewer that knows
@@ -39469,6 +39554,12 @@ Object.freeze({
39469
39554
  addonId: null,
39470
39555
  access: "view"
39471
39556
  },
39557
+ "pipelineAnalytics.ownersWithMedia": {
39558
+ capName: "pipeline-analytics",
39559
+ capScope: "device",
39560
+ addonId: null,
39561
+ access: "view"
39562
+ },
39472
39563
  "pipelineAnalytics.pauseForStorageMigration": {
39473
39564
  capName: "pipeline-analytics",
39474
39565
  capScope: "device",
@@ -43369,6 +43460,11 @@ Object.freeze({
43369
43460
  form: "single",
43370
43461
  optional: false
43371
43462
  }],
43463
+ "pipelineAnalytics.ownersWithMedia": [{
43464
+ name: "deviceId",
43465
+ form: "single",
43466
+ optional: false
43467
+ }],
43372
43468
  "pipelineAnalytics.proposeRetrainAnnotations": [{
43373
43469
  name: "deviceId",
43374
43470
  form: "single",
@@ -45839,4 +45935,4 @@ function enumerateInferenceDevices(hw) {
45839
45935
  return out;
45840
45936
  }
45841
45937
  //#endregion
45842
- export { failureContributionCapability as $, hydrateSchema as $t, RingBuffer as A, runtimeDevices as At, declareLogChannel as B, buildFfmpegArgs as Bt, OpsLogEntrySchema as C, recordingExportCapability as Ct, RECORDING_EXPORT_MAX_READ_BYTES as D, resolveLocationMode as Dt, RATE_CONTROL_TIGHT as E, resolveEgressDecodeHwAccel as Et, audioKindId as F, supportedRuntimes as Ft, detectionPipelineCapability as G, CAM_PROFILE_ORDER as Gt, deriveBatteryPresence as H, isSoftwareDecode as Ht, batteryCapability as I, webrtcSessionCapability as It, enumerateInferenceDevices as J, audioChunkBytesPerSample as Jt, egressTranscodeSharingKey as K, DeviceFeature as Kt, cameraStreamsCapability as L, errMsg as Lt, addonWidgetsSourceCapability as M, storageOccupancyCapability as Mt, audioAnalysisCapability as N, streamBrokerCapability as Nt, RecordingConfigSchema as O, resolvePoolMemoryPolicy as Ot, audioAnalyzerCapability as P, stripRetiredBandPreBufferSec as Pt, evictionPolicyOfLocation as Q, expandAudioChunkToF32le as Qt, createHwAccelCache as R, AUDIO_PRESETS as Rt, NativeLeaseSettingsSchema as S, recordingCapability as St, RATE_CONTROL_RELAXED as T, resolveClusterStepModelId as Tt, deriveDetailCropRect as U, BOOT_RECOVERY_BACKOFF_MS as Ut, defaultDeviceFor as V, invocationFromEncodeProfile as Vt, deriveRecordingMode as W, BaseAddon as Wt, evaluateZoneRules as X, customAction as Xt, evaluateSensorEdge as Y, createEvent as Yt, evictionPolicyForMode as Z, defineCustomActions as Zt, FailureCounters as _, record as _n, pickDetailCropConvention as _t, COCO_80_LABELS as a, parseProfileBrokerId as an, logChannelsCapability as at, MOTION_CLOSE_AFTER_MS as b, EventCategory as bn, pipelineRunnerCapability as bt, DEFAULT_CLUSTER_STEP_MODELS as c, _enum as cn, mayReadLocation as ct, DEFAULT_EVENTS_BAND_BUFFER_SEC as d, discriminatedUnion as dn, modeMayWrite as dt, isEvent as en, gbToBytes as et, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as f, lazy as fn, motionDetectionCapability as ft, ExportRecordSchema as g, preprocess as gn, pickClusterStepSettings as gt, EncodeProfileSchema as h, object as hn, pickClusterStepModels as ht, BatteryStatusSchema as i, parseJsonUnknown as in, loadContributionCapability as it, YAMNET_TO_MACRO as j, storageEvictableCapability as jt, RecordingSignalStatusSchema as k, resolveRecordingProfiles as kt, DEFAULT_CLUSTER_STEP_SETTINGS as l, array as ln, mayWriteToLocation as lt, DEVICE_BACKEND_TO_FORMAT as m, number as mn, parseProcStatus as mt, AUDIO_BACKEND_CHOICES as n, makeSourceBrokerId as nn, inferModelProvider as nt, COCO_TO_MACRO as o, selectAssignedProfileSlots as on, mapAudioLabelToMacro as ot, DEFAULT_NATIVE_LEASE_SETTINGS as p, literal as pn, overlayClusterStepSettings as pt, egressTransportFromRequest as q, DeviceType as qt, AUDIO_MACRO_LABELS as r, nodePin as rn, isFirstLevelMacroClass as rt, DEFAULT_AUDIO_ANALYZER_CONFIG as s, sleep as sn, maskUrlCredentials as st, APPLE_SA_TO_MACRO as t, makeProfileBrokerId as tn, hfModelUrl as tt, DEFAULT_DETAIL_CROP_CONVENTION as u, boolean as un, migrateLegacyDeviceSignalConfig as ut, G711_SCALE_CORRECTION_DB as v, string as vn, pickNativeLeaseOverride as vt, PoolMemoryWatchdog as w, recordingSignalCapability as wt, NativeLeaseAdmissionSchema as x, rankStreams as xt, HF_BASE_URL as y, union as yn, pipelineExecutorCapability as yt, createLogChannelsProvider as z, Fmp4BoxSplitter as zt };
45938
+ export { evaluateZoneRules as $, createEvent as $t, RecordingConfigSchema as A, resolveLocationMode as At, cameraStreamsCapability as B, webrtcSessionCapability as Bt, NativeLeaseAdmissionSchema as C, union as Cn, pipelineRunnerCapability as Ct, RATE_CONTROL_RELAXED as D, recordingSignalCapability as Dt, PoolMemoryWatchdog as E, recordingExportCapability as Et, addonWidgetsSourceCapability as F, storageOccupancyCapability as Ft, deriveBatteryPresence as G, invocationFromEncodeProfile as Gt, createLogChannelsProvider as H, AUDIO_PRESETS as Ht, audioAnalysisCapability as I, streamBrokerCapability as It, detectionPipelineCapability as J, BaseAddon as Jt, deriveDetailCropRect as K, isSoftwareDecode as Kt, audioAnalyzerCapability as L, stripRetiredBandPreBufferSec as Lt, RingBuffer as M, resolveRecordingProfiles as Mt, VISIT_MERGE_GAP_MS as N, runtimeDevices as Nt, RATE_CONTROL_TIGHT as O, resolveClusterStepModelId as Ot, YAMNET_TO_MACRO as P, storageEvictableCapability as Pt, evaluateSensorEdge as Q, audioChunkBytesPerSample as Qt, audioKindId as R, supportedRuntimes as Rt, MOTION_CLOSE_AFTER_MS as S, string as Sn, pipelineExecutorCapability as St, OpsLogEntrySchema as T, recordingCapability as Tt, declareLogChannel as U, Fmp4BoxSplitter as Ut, createHwAccelCache as V, errMsg as Vt, defaultDeviceFor as W, buildFfmpegArgs as Wt, egressTransportFromRequest as X, DeviceFeature as Xt, egressTranscodeSharingKey as Y, CAM_PROFILE_ORDER as Yt, enumerateInferenceDevices as Z, DeviceType as Zt, EncodeProfileSchema as _, literal as _n, parseProcStatus as _t, COCO_80_LABELS as a, makeProfileBrokerId as an, inferModelProvider as at, G711_SCALE_CORRECTION_DB as b, preprocess as bn, pickDetailCropConvention as bt, DEFAULT_CLUSTER_STEP_MODELS as c, parseJsonUnknown as cn, logChannelsCapability as ct, DEFAULT_EVENTS_BAND_BUFFER_SEC as d, sleep as dn, mayReadLocation as dt, customAction as en, evictionPolicyForMode as et, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as f, _enum as fn, mayWriteToLocation as ft, EVENT_PAD_MS as g, lazy as gn, overlayClusterStepSettings as gt, EVENT_OWNER_TYPES as h, discriminatedUnion as hn, motionDetectionCapability as ht, BatteryStatusSchema as i, isEvent as in, hfModelUrl as it, RecordingSignalStatusSchema as j, resolvePoolMemoryPolicy as jt, RECORDING_EXPORT_MAX_READ_BYTES as k, resolveEgressDecodeHwAccel as kt, DEFAULT_CLUSTER_STEP_SETTINGS as l, parseProfileBrokerId as ln, mapAudioLabelToMacro as lt, DEVICE_BACKEND_TO_FORMAT as m, boolean as mn, modeMayWrite as mt, AUDIO_BACKEND_CHOICES as n, expandAudioChunkToF32le as nn, failureContributionCapability as nt, COCO_TO_MACRO as o, makeSourceBrokerId as on, isFirstLevelMacroClass as ot, DEFAULT_NATIVE_LEASE_SETTINGS as p, array as pn, migrateLegacyDeviceSignalConfig as pt, deriveRecordingMode as q, BOOT_RECOVERY_BACKOFF_MS as qt, AUDIO_MACRO_LABELS as r, hydrateSchema as rn, gbToBytes as rt, DEFAULT_AUDIO_ANALYZER_CONFIG as s, nodePin as sn, loadContributionCapability as st, APPLE_SA_TO_MACRO as t, defineCustomActions as tn, evictionPolicyOfLocation as tt, DEFAULT_DETAIL_CROP_CONVENTION as u, selectAssignedProfileSlots as un, maskUrlCredentials as ut, ExportRecordSchema as v, number as vn, pickClusterStepModels as vt, NativeLeaseSettingsSchema as w, EventCategory as wn, rankStreams as wt, HF_BASE_URL as x, record as xn, pickNativeLeaseOverride as xt, FailureCounters as y, object as yn, pickClusterStepSettings as yt, batteryCapability as z, videoclipsCapability as zt };