@camstack/addon-post-analysis 1.2.661 → 1.2.663

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 (16) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/{clip-model-registry-CVajwmEk.mjs → clip-model-registry-CwXJyrLg.mjs} +34398 -33387
  3. package/dist/{clip-model-registry-RvEPUqvS.js → clip-model-registry-Cz8LWYwU.js} +34398 -33387
  4. package/dist/embedding-encoder/index.js +1 -1
  5. package/dist/embedding-encoder/index.mjs +1 -1
  6. package/dist/pipeline-analytics/_stub.js +2 -2
  7. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CwKrui6c.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-jPBj20ez.mjs} +2 -2
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Be6bZvOS.mjs +26 -0
  9. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-B5Bw-VHt.mjs +26 -0
  10. package/dist/pipeline-analytics/{hostInit-DR75U6YM.mjs → hostInit-DOdK6KJ5.mjs} +2 -2
  11. package/dist/pipeline-analytics/index.js +391 -31
  12. package/dist/pipeline-analytics/index.mjs +391 -31
  13. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  14. package/package.json +2 -2
  15. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BDKliSzv.mjs +0 -26
  16. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BGdtpHOa.mjs +0 -26
@@ -1,4 +1,4 @@
1
- import { $ as MAX_TRACK_RELATIONS, $i as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, $n as bundledCamstack, $r as normalizeNcAction, $t as NcTemplateVarDescriptorSchema, A as DETECTION_MACRO_CLASSES, Aa as strictObject, Ai as sceneMonitorCapability, An as TrackPuritySchema, Ar as isAlertEpisodeOpen, At as NcAlarmConfigSchema, B as EXPORT_DENSE_MAX_RANGES, Bi as sunTimes, Bn as alertEpisodeKind, Br as isLabelSupplyStepId, Bt as NcRuleSchema, C as COCO_TO_MACRO, Ca as discriminatedUnion, Ci as retrainRevisionConflictMessage, Cn as SetTrackRelationInputSchema, Cr as eventKindLabel, Ct as NC_GROUPING_MIN_SEC, D as DEFAULT_DETAIL_CROP_CONVENTION, Da as object, Di as ruleDeviceCompatCapQueries, Dn as TimelapseRulePatchSchema, Dr as gifDeriveSpeed, Dt as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, E as CoverStateSchema, Ea as number, Ei as ruleBelongsToAlarm$1, En as TimelapseRuleInputSchema, Er as failureContributionCapability, Et as NC_STATE_SUMMARY_SECTION_IDS, F as EMBEDDING_REQUIREMENTS_FAILED, Fa as unknown, Fi as storageOccupancyCapability, Fn as activateAlarmProfile, Fr as isDetectionMacroClass, Ft as NcConditionDescriptorSchema, G as LabelAttributionSchema, Gi as systemEventSummaryScheduleOf, Gn as applySecureOnArmEdit, Gr as isSystemDelivery, Gt as NcSnoozeInputSchema, H as FULL_IMAGE_BBOX, Hi as systemEventDeliveryProblems, Hn as applyBlockingEdit, Hr as isRetiredClearKey, Ht as NcRuleUpdateInputSchema, I as EMBEDDING_REQUIREMENTS_UNAVAILABLE, Ia as DeviceType, Ii as subKindsOf, In as addonWidgetsSourceCapability, Ir as isDrawableSubjectPath, It as NcConditionsSchema, J as LockStateSchema, Ji as templateVarsFor, Jn as audioMetricsCapability, Jr as kebabToCamel, Jt as NcStateSummarySectionIdSchema, K as ListTrackRelationsInputSchema, Ki as systemEventSummarySplitOf, Kn as armRemovalReconcile, Kr as isSystemEventSummaryRule, Kt as NcSnoozeSchema, L as EVENT_DENSITY_BATCH_MAX, La as errMsg, Li as subjectPathSampleFromBox, Ln as alarmDeviceSecureOnArm, Lr as isEventKindLabelKey, Lt as NcRuleActionSchema, M as DeclaredDevices, Ma as templateLiteral, Mi as sensorRaisedOf, Mn as TrackRelationSchema, Mr as isAppLinkBase, Mt as NcAlarmSensorsInputSchema, N as DetectionSourceSchema, Na as tuple, Ni as servedTemplateVars, Nn as TrackSideSchema, Nr as isAudioClassName, Nt as NcAlarmSensorsSchema, O as DEFAULT_EVENT_COLOR, Oa as partialRecord, Oi as ruleGroupingApplies, On as TimelapseRuleSchema, Or as gifFromMp4Args, Ot as NC_TAXONOMY, P as EMBEDDING_MODEL_FAILED, Pa as union, Pi as startMoverUnderClearance, Pn as TrackSourceSchema, Pr as isDefaultAlarmProfileId, Pt as NcAlarmSettingsPatchSchema, Q as MAX_TRACK_PURITIES, Qi as zoneAnalyticsCapability, Qn as buildViewerLink, Qr as ncMediaPolicyError, Qt as NcTemplatePreviewSchema, R as EVENT_KIND_BY_CAP, Ra as EventCategory, Ri as subjectPathSvgPoints, Rn as alarmPanelCapability, Rr as isEventOwnerType, Rt as NcRuleInputSchema, S as BucketAccumulator, Sa as boolean, Sn as SetTrackPurityResultSchema, Sr as ensureAlarmProfiles, St as NC_GROUPING_MAX_SEC, T as ClearTrackRelationResultSchema, Ta as looseObject, Ti as ruleAutoTriggersAlarm, Tn as TRACK_RELATIONS_DEFAULT_LIMIT, Tr as faceGalleryCapability, Tt as NC_SNOOZE_MAX_MINUTES, U as FailureCounters, Ui as systemEventFamilyProblems, Un as applyModeDelaysEdits, Ur as isRootSuppliableStepId, Ut as NcScheduleSchema, V as FIRST_LEVEL_MACRO_CLASSES, Vi as syncActiveAlarmProfileSettings, Vn as alertEpisodePayload, Vr as isMediaOwnerType, Vt as NcRuleTargetSchema, W as LABEL_SUPPLY_MACRO, Wi as systemEventFilterApplies, Wn as applyNonBlockingEdit, Wr as isScheduleActive, Wt as NcSharedSequenceSchema, X as MAX_BIRTH_DECISION_RECORDS, Xi as viewerLinkBaseOf, Xn as buildEventKindDescriptor, Xr as mayWriteToLocation, Xt as NcTaxonomySchema, Y as MAX_ARCHIVED_DEBUG_NOTES, Yi as vectorDimFromBase64, Yn as audioModeOf, Yr as linkedStepOf, Yt as NcSystemEventKindSchema, Z as MAX_BIRTH_LATENCY_PROXY_MS, Zi as withSystemEventClasses, Zn as buildSubjectPath, Zr as memoizePinnedFfmpeg, Zt as NcTemplatePreviewInputSchema, _ as AlarmArmModeSchema, _i as resolveDeliveryParams, _n as SCENE_DEFAULT_UNCOVERED_POLICY, _t as NC_CONFIRM_DEFAULT_TIMEOUT_MS, a as CLIP_EMBEDDING_STEP_ID, aa as CamProfileSchema, ai as paletteResultSchema, an as RECORDING_SOURCE_CAMSTACK_ADDON, ar as coreBlockIdFromAddonId, at as NC_ALARM_DELAY_FIELDS, b as BaseDevice, ba as _enum, bi as resolveModeNotifyPolicy, bn as SceneMonitorSchema, bt as NC_DEFAULT_SNOOZE_MINUTES, c as readClusterModelPinStrict, ca as RECORD_QUERY_MAX, ci as pickFaceRescoreIntervalMinutes, cn as RetrainOriginSchema, cr as deleteAlarmProfile, ct as NC_ALARM_SYSTEM_EVENT_KINDS, d as APPEARANCE_BIN_COUNT, da as defineAddonMigrations, di as projectSubjectPath, dn as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, dr as deriveRecordingMode, dt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, ea as canonicalHash, ei as normalizeNcCapTarget, en as OPS_LOG_DEFAULT_LIMIT, er as calendarEventLocalSpan, et as MOTION_CLOSE_AFTER_MS, f as APPEARANCE_BLOCKS, fa as defineCustomActions, fi as readDeviceStateFrom, fn as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, fr as describeSystemEventDeliveryProblem, ft as NC_CLIP_POST_ROLL_DEFAULT_SEC, g as ActionTargetResolver, ga as nodePin, gi as resolveClipSearchMinScore, gn as SCENE_DEFAULT_QUIET_SECONDS, gt as NC_CONFIRM_DEFAULT_MAX_IMAGE_PX, h as AUDIO_MACRO_LABELS, ha as isDeviceScopedCap, hi as renameAlarmProfile, hn as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, hr as deviceRemovalHookCapability, ht as NC_CONDITION_CATALOG, ia as CAP_ADVANCE_FIELDS, ii as paintHex, in as RECORDING_EXPORT_MAX_READ_BYTES, ir as consumableLowPercentOf, it as NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC, j as DETECTION_PIPELINE_CAP_NAME, ja as string, ji as secureActuationFor, jn as TrackRelationKindSchema, jr as isAlertEpisodeSeverity, jt as NcAlarmPostTriggeredActionSchema, k as DEFAULT_TIMELAPSE_PREVIEW_TEXT, ka as record, ki as ruleKindOf, kn as TrackPlacementSchema, kr as isAlarmControllableCap, kt as NC_TEMPLATE_VARS, l as resolveClusterModelPin, la as createEvent, li as pipelineAnalyticsCapability, ln as RetrainStatusSchema, lr as deriveDetailCropRect, lt as NC_ALARM_TRIGGERED_MAX_SEC, m as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, ma as hydrateSchema, mi as readTimelapseGeneratedAt, mn as SCENE_DEFAULT_CHECK_INTERVAL_SEC, mr as deviceAttentionKind, mt as NC_CLIP_RETENTION_MAX_SEC, na as isSourceCap, ni as notificationRulesCapability, nn as PackageLlmVerdictSchema, nr as cloneAlarmSettings, nt as MotionTriggeredBySchema, o as CLUSTER_MODEL_OWNER_ADDON_ID, oa as InvalidRecordError, oi as parseAlertEpisodePayload, on as RebuildObjectEmbeddingsRefusalSchema, or as cosineSimilarity$1, ot as NC_ALARM_DELAY_MAX_SEC, p as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, pa as defineRecordKinds, pi as readMotionTriggeredBy, pn as SCENE_DEFAULT_ANCHOR_THRESHOLD, pr as describeSystemEventFamilyProblem, pt as NC_CLIP_PRE_ROLL_DEFAULT_SEC, q as ListTrackRelationsResultSchema, qi as templateCarriesSummary, qn as assertTimelapseCadences, qr as isVectorIndexDimConflict, qt as NcSnoozeSuppressedSchema, ra as BaseAddon, ri as occupancyScope, rr as consumableFormOf, rt as NC_ALARM_DEFAULT_PROFILE_ID, s as FACE_EMBEDDING_STEP_ID, sa as RECORD_MAX_DATA_BYTES, sn as RetrainDismissedSchema, sr as createAlarmProfile, st as NC_ALARM_NOTIFY_FIELDS, t as BUILTIN_CLIP_MODELS, ta as evaluateSensorEdge, ti as normalizeNcMediaPolicy, tn as OpsLogEntrySchema, tr as classifyRetrainReview, tt as MediaFileKindEnum, u as ACTION_TARGET_INVALIDATION_EVENTS, ua as customAction, ui as plateGalleryCapability, un as RetrainVerdictSubjectSchema, ur as derivePostTriggeredAction, ut as NC_AUDIO_CONFIRM_HITS_DEFAULT, v as ArchivedDebugNoteSchema, va as sleep$1, vi as resolveLocationMode, vn as SCENE_DIVERGED, vr as embeddingRefusalOf, vt as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, w as ClearTrackRelationInputSchema, wa as literal, wi as rootSupplyServes, wn as TIMELAPSE_DENSE_FLOOR_SEC, wr as evictionPolicyOfLocation, wt as NC_SENSOR_TRANSITION_KINDS, x as BirthDecisionRecordSchema, xa as array, xi as resolveNcMediaImage, xn as SetTrackPurityInputSchema, xr as encodeVectorBase64, xt as NC_GROUPING_DEFAULT_SEC, y as BIRTH_DECISION_DEFAULT_LIMIT, ya as ZodObject, yi as resolveModeDelays, yn as SCENE_RESET_RECAPTURES, yt as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, z as EVENT_OWNER_TYPES, zi as summarizeReview, zn as alertEpisodeId, zr as isKnownTemplateVar, zt as NcRulePatchSchema } from "../clip-model-registry-CVajwmEk.mjs";
1
+ import { $ as MAX_TRACK_RELATIONS, $i as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, $n as bundledCamstack, $r as normalizeNcAction, $t as NcTemplateVarDescriptorSchema, A as DETECTION_MACRO_CLASSES, Aa as strictObject, Ai as sceneMonitorCapability, An as TrackPuritySchema, Ar as isAlertEpisodeOpen, At as NcAlarmConfigSchema, B as EXPORT_DENSE_MAX_RANGES, Bi as sunTimes, Bn as alertEpisodeKind, Br as isLabelSupplyStepId, Bt as NcRuleSchema, C as COCO_TO_MACRO, Ca as discriminatedUnion, Ci as retrainRevisionConflictMessage, Cn as SetTrackRelationInputSchema, Cr as eventKindLabel, Ct as NC_GROUPING_MIN_SEC, D as DEFAULT_DETAIL_CROP_CONVENTION, Da as object, Di as ruleDeviceCompatCapQueries, Dn as TimelapseRulePatchSchema, Dr as gifDeriveSpeed, Dt as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, E as CoverStateSchema, Ea as number, Ei as ruleBelongsToAlarm$1, En as TimelapseRuleInputSchema, Er as failureContributionCapability, Et as NC_STATE_SUMMARY_SECTION_IDS, F as EMBEDDING_REQUIREMENTS_FAILED, Fa as unknown, Fi as storageOccupancyCapability, Fn as activateAlarmProfile, Fr as isDetectionMacroClass, Ft as NcConditionDescriptorSchema, G as LabelAttributionSchema, Gi as systemEventSummaryScheduleOf, Gn as applySecureOnArmEdit, Gr as isSystemDelivery, Gt as NcSnoozeInputSchema, H as FULL_IMAGE_BBOX, Hi as systemEventDeliveryProblems, Hn as applyBlockingEdit, Hr as isRetiredClearKey, Ht as NcRuleUpdateInputSchema, I as EMBEDDING_REQUIREMENTS_UNAVAILABLE, Ia as DeviceType, Ii as subKindsOf, In as addonWidgetsSourceCapability, Ir as isDrawableSubjectPath, It as NcConditionsSchema, J as LockStateSchema, Ji as templateVarsFor, Jn as audioMetricsCapability, Jr as kebabToCamel, Jt as NcStateSummarySectionIdSchema, K as ListTrackRelationsInputSchema, Ki as systemEventSummarySplitOf, Kn as armRemovalReconcile, Kr as isSystemEventSummaryRule, Kt as NcSnoozeSchema, L as EVENT_DENSITY_BATCH_MAX, La as errMsg, Li as subjectPathSampleFromBox, Ln as alarmDeviceSecureOnArm, Lr as isEventKindLabelKey, Lt as NcRuleActionSchema, M as DeclaredDevices, Ma as templateLiteral, Mi as sensorRaisedOf, Mn as TrackRelationSchema, Mr as isAppLinkBase, Mt as NcAlarmSensorsInputSchema, N as DetectionSourceSchema, Na as tuple, Ni as servedTemplateVars, Nn as TrackSideSchema, Nr as isAudioClassName, Nt as NcAlarmSensorsSchema, O as DEFAULT_EVENT_COLOR, Oa as partialRecord, Oi as ruleGroupingApplies, On as TimelapseRuleSchema, Or as gifFromMp4Args, Ot as NC_TAXONOMY, P as EMBEDDING_MODEL_FAILED, Pa as union, Pi as startMoverUnderClearance, Pn as TrackSourceSchema, Pr as isDefaultAlarmProfileId, Pt as NcAlarmSettingsPatchSchema, Q as MAX_TRACK_PURITIES, Qi as zoneAnalyticsCapability, Qn as buildViewerLink, Qr as ncMediaPolicyError, Qt as NcTemplatePreviewSchema, R as EVENT_KIND_BY_CAP, Ra as EventCategory, Ri as subjectPathSvgPoints, Rn as alarmPanelCapability, Rr as isEventOwnerType, Rt as NcRuleInputSchema, S as BucketAccumulator, Sa as boolean, Sn as SetTrackPurityResultSchema, Sr as ensureAlarmProfiles, St as NC_GROUPING_MAX_SEC, T as ClearTrackRelationResultSchema, Ta as looseObject, Ti as ruleAutoTriggersAlarm, Tn as TRACK_RELATIONS_DEFAULT_LIMIT, Tr as faceGalleryCapability, Tt as NC_SNOOZE_MAX_MINUTES, U as FailureCounters, Ui as systemEventFamilyProblems, Un as applyModeDelaysEdits, Ur as isRootSuppliableStepId, Ut as NcScheduleSchema, V as FIRST_LEVEL_MACRO_CLASSES, Vi as syncActiveAlarmProfileSettings, Vn as alertEpisodePayload, Vr as isMediaOwnerType, Vt as NcRuleTargetSchema, W as LABEL_SUPPLY_MACRO, Wi as systemEventFilterApplies, Wn as applyNonBlockingEdit, Wr as isScheduleActive, Wt as NcSharedSequenceSchema, X as MAX_BIRTH_DECISION_RECORDS, Xi as viewerLinkBaseOf, Xn as buildEventKindDescriptor, Xr as mayWriteToLocation, Xt as NcTaxonomySchema, Y as MAX_ARCHIVED_DEBUG_NOTES, Yi as vectorDimFromBase64, Yn as audioModeOf, Yr as linkedStepOf, Yt as NcSystemEventKindSchema, Z as MAX_BIRTH_LATENCY_PROXY_MS, Zi as withSystemEventClasses, Zn as buildSubjectPath, Zr as memoizePinnedFfmpeg, Zt as NcTemplatePreviewInputSchema, _ as AlarmArmModeSchema, _i as resolveDeliveryParams, _n as SCENE_DEFAULT_UNCOVERED_POLICY, _t as NC_CONFIRM_DEFAULT_TIMEOUT_MS, a as CLIP_EMBEDDING_STEP_ID, aa as CamProfileSchema, ai as paletteResultSchema, an as RECORDING_SOURCE_CAMSTACK_ADDON, ar as coreBlockIdFromAddonId, at as NC_ALARM_DELAY_FIELDS, b as BaseDevice, ba as _enum, bi as resolveModeNotifyPolicy, bn as SceneMonitorSchema, bt as NC_DEFAULT_SNOOZE_MINUTES, c as readClusterModelPinStrict, ca as RECORD_QUERY_MAX, ci as pickFaceRescoreIntervalMinutes, cn as RetrainOriginSchema, cr as deleteAlarmProfile, ct as NC_ALARM_SYSTEM_EVENT_KINDS, d as APPEARANCE_BIN_COUNT, da as defineAddonMigrations, di as projectSubjectPath, dn as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, dr as deriveRecordingMode, dt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, ea as canonicalHash, ei as normalizeNcCapTarget, en as OPS_LOG_DEFAULT_LIMIT, er as calendarEventLocalSpan, et as MOTION_CLOSE_AFTER_MS, f as APPEARANCE_BLOCKS, fa as defineCustomActions, fi as readDeviceStateFrom, fn as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, fr as describeSystemEventDeliveryProblem, ft as NC_CLIP_POST_ROLL_DEFAULT_SEC, g as ActionTargetResolver, ga as nodePin, gi as resolveClipSearchMinScore, gn as SCENE_DEFAULT_QUIET_SECONDS, gt as NC_CONFIRM_DEFAULT_MAX_IMAGE_PX, h as AUDIO_MACRO_LABELS, ha as isDeviceScopedCap, hi as renameAlarmProfile, hn as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, hr as deviceRemovalHookCapability, ht as NC_CONDITION_CATALOG, ia as CAP_ADVANCE_FIELDS, ii as paintHex, in as RECORDING_EXPORT_MAX_READ_BYTES, ir as consumableLowPercentOf, it as NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC, j as DETECTION_PIPELINE_CAP_NAME, ja as string, ji as secureActuationFor, jn as TrackRelationKindSchema, jr as isAlertEpisodeSeverity, jt as NcAlarmPostTriggeredActionSchema, k as DEFAULT_TIMELAPSE_PREVIEW_TEXT, ka as record, ki as ruleKindOf, kn as TrackPlacementSchema, kr as isAlarmControllableCap, kt as NC_TEMPLATE_VARS, l as resolveClusterModelPin, la as createEvent, li as pipelineAnalyticsCapability, ln as RetrainStatusSchema, lr as deriveDetailCropRect, lt as NC_ALARM_TRIGGERED_MAX_SEC, m as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, ma as hydrateSchema, mi as readTimelapseGeneratedAt, mn as SCENE_DEFAULT_CHECK_INTERVAL_SEC, mr as deviceAttentionKind, mt as NC_CLIP_RETENTION_MAX_SEC, na as isSourceCap, ni as notificationRulesCapability, nn as PackageLlmVerdictSchema, nr as cloneAlarmSettings, nt as MotionTriggeredBySchema, o as CLUSTER_MODEL_OWNER_ADDON_ID, oa as InvalidRecordError, oi as parseAlertEpisodePayload, on as RebuildObjectEmbeddingsRefusalSchema, or as cosineSimilarity$1, ot as NC_ALARM_DELAY_MAX_SEC, p as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, pa as defineRecordKinds, pi as readMotionTriggeredBy, pn as SCENE_DEFAULT_ANCHOR_THRESHOLD, pr as describeSystemEventFamilyProblem, pt as NC_CLIP_PRE_ROLL_DEFAULT_SEC, q as ListTrackRelationsResultSchema, qi as templateCarriesSummary, qn as assertTimelapseCadences, qr as isVectorIndexDimConflict, qt as NcSnoozeSuppressedSchema, ra as BaseAddon, ri as occupancyScope, rr as consumableFormOf, rt as NC_ALARM_DEFAULT_PROFILE_ID, s as FACE_EMBEDDING_STEP_ID, sa as RECORD_MAX_DATA_BYTES, sn as RetrainDismissedSchema, sr as createAlarmProfile, st as NC_ALARM_NOTIFY_FIELDS, t as BUILTIN_CLIP_MODELS, ta as evaluateSensorEdge, ti as normalizeNcMediaPolicy, tn as OpsLogEntrySchema, tr as classifyRetrainReview, tt as MediaFileKindEnum, u as ACTION_TARGET_INVALIDATION_EVENTS, ua as customAction, ui as plateGalleryCapability, un as RetrainVerdictSubjectSchema, ur as derivePostTriggeredAction, ut as NC_AUDIO_CONFIRM_HITS_DEFAULT, v as ArchivedDebugNoteSchema, va as sleep$1, vi as resolveLocationMode, vn as SCENE_DIVERGED, vr as embeddingRefusalOf, vt as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, w as ClearTrackRelationInputSchema, wa as literal, wi as rootSupplyServes, wn as TIMELAPSE_DENSE_FLOOR_SEC, wr as evictionPolicyOfLocation, wt as NC_SENSOR_TRANSITION_KINDS, x as BirthDecisionRecordSchema, xa as array, xi as resolveNcMediaImage, xn as SetTrackPurityInputSchema, xr as encodeVectorBase64, xt as NC_GROUPING_DEFAULT_SEC, y as BIRTH_DECISION_DEFAULT_LIMIT, ya as ZodObject, yi as resolveModeDelays, yn as SCENE_RESET_RECAPTURES, yt as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, z as EVENT_OWNER_TYPES, zi as summarizeReview, zn as alertEpisodeId, zr as isKnownTemplateVar, zt as NcRulePatchSchema } from "../clip-model-registry-CwXJyrLg.mjs";
2
2
  import { t as __exportAll } from "../embedding-encoder/index.mjs";
3
3
  import * as fs$1 from "node:fs";
4
4
  import { createWriteStream, promises } from "node:fs";
@@ -8942,6 +8942,17 @@ var en_default = {
8942
8942
  "detection.subject.identity": "{{label}}",
8943
8943
  "detection.subject.plate": "{{classNoun}} {{label}}",
8944
8944
  "detection.inZones": " in {{zones}}",
8945
+ "appliance.finished.title": "{{device}} finished",
8946
+ "appliance.finished.body": "{{device}} finished{{afterDuration}}{{usedEnergy}}",
8947
+ "appliance.finished.duration": " after {{duration}}",
8948
+ "appliance.finished.energy": " and used {{energy}}",
8949
+ "appliance.duration.minutes": {
8950
+ "one": "{{minutes}} minute",
8951
+ "other": "{{minutes}} minutes"
8952
+ },
8953
+ "appliance.duration.hours": "{{hours}} h",
8954
+ "appliance.duration.hoursMinutes": "{{hours}} h {{minutes}} min",
8955
+ "appliance.energy.value": "{{value}} kWh",
8945
8956
  "class.person": {
8946
8957
  "one": "person",
8947
8958
  "other": "people"
@@ -9348,6 +9359,17 @@ var it_default = {
9348
9359
  "detection.subject.identity": "{{label}}",
9349
9360
  "detection.subject.plate": "{{classNoun}} {{label}}",
9350
9361
  "detection.inZones": " in {{zones}}",
9362
+ "appliance.finished.title": "{{device}} ha terminato",
9363
+ "appliance.finished.body": "{{device}} ha terminato{{afterDuration}}{{usedEnergy}}",
9364
+ "appliance.finished.duration": " dopo {{duration}}",
9365
+ "appliance.finished.energy": " e ha consumato {{energy}}",
9366
+ "appliance.duration.minutes": {
9367
+ "one": "{{minutes}} minuto",
9368
+ "other": "{{minutes}} minuti"
9369
+ },
9370
+ "appliance.duration.hours": "{{hours}} h",
9371
+ "appliance.duration.hoursMinutes": "{{hours}} h {{minutes}} min",
9372
+ "appliance.energy.value": "{{value}} kWh",
9351
9373
  "class.person": {
9352
9374
  "one": "persona",
9353
9375
  "other": "persone"
@@ -68608,6 +68630,109 @@ function createAnalyticsWidgetsProvider() {
68608
68630
  ] };
68609
68631
  }
68610
68632
  //#endregion
68633
+ //#region src/notification-center/appliance-cycle.ts
68634
+ var NC_UNKNOWN_CYCLE_FACTS = {
68635
+ durationMs: null,
68636
+ energyKwh: null
68637
+ };
68638
+ var NC_EMPTY_CYCLE_VARS = {
68639
+ duration: "",
68640
+ energy: "",
68641
+ afterDuration: "",
68642
+ usedEnergy: ""
68643
+ };
68644
+ /** `52 minutes` / `1 h 12 min` / `2 h`; `''` below one minute (never "0 minutes"). */
68645
+ function durationText(texts, durationMs) {
68646
+ if (durationMs === null || !Number.isFinite(durationMs)) return "";
68647
+ const totalMinutes = Math.round(durationMs / 6e4);
68648
+ if (totalMinutes < 1) return "";
68649
+ if (totalMinutes < 60) return texts.text({
68650
+ key: "appliance.duration.minutes",
68651
+ count: totalMinutes,
68652
+ vars: { minutes: `${totalMinutes}` }
68653
+ });
68654
+ const hours = Math.floor(totalMinutes / 60);
68655
+ const minutes = totalMinutes % 60;
68656
+ return minutes === 0 ? texts.text({
68657
+ key: "appliance.duration.hours",
68658
+ vars: { hours: `${hours}` }
68659
+ }) : texts.text({
68660
+ key: "appliance.duration.hoursMinutes",
68661
+ vars: {
68662
+ hours: `${hours}`,
68663
+ minutes: `${minutes}`
68664
+ }
68665
+ });
68666
+ }
68667
+ /** `0,84 kWh` (it) / `0.84 kWh` (en); `''` when unmeasured. */
68668
+ function energyText(texts, energyKwh) {
68669
+ if (energyKwh === null || !Number.isFinite(energyKwh) || energyKwh < 0) return "";
68670
+ const value = energyKwh.toLocaleString(texts.language, {
68671
+ minimumFractionDigits: 2,
68672
+ maximumFractionDigits: 2
68673
+ });
68674
+ return texts.text({
68675
+ key: "appliance.energy.value",
68676
+ vars: { value }
68677
+ });
68678
+ }
68679
+ /** The four variables of a finished cycle, fragments rendered from scalars only. */
68680
+ function ncApplianceCycleVars(texts, facts) {
68681
+ const duration = durationText(texts, facts.durationMs);
68682
+ const energy = energyText(texts, facts.energyKwh);
68683
+ return {
68684
+ duration,
68685
+ energy,
68686
+ afterDuration: duration === "" ? "" : texts.text({
68687
+ key: "appliance.finished.duration",
68688
+ vars: { duration }
68689
+ }),
68690
+ usedEnergy: energy === "" ? "" : texts.text({
68691
+ key: "appliance.finished.energy",
68692
+ vars: { energy }
68693
+ })
68694
+ };
68695
+ }
68696
+ /**
68697
+ * The frozen reference a FINISHED appliance cycle row carries (`{}` for every
68698
+ * other row): kind `appliance-cycle`, edge `cleared`. The appliance is the
68699
+ * sensor itself — a linked camera is only where the row was attributed.
68700
+ */
68701
+ function applianceCycleOf(subject) {
68702
+ if (subject.sensorKind !== "appliance-cycle" || subject.sensorRaised !== false) return {};
68703
+ return { applianceCycle: { deviceId: subject.linkedSensorId ?? subject.sourceDeviceId ?? subject.deviceId } };
68704
+ }
68705
+ //#endregion
68706
+ //#region src/notification-center/appliance-cycle-runs.ts
68707
+ var CYCLE_FACTS_WAIT_MS = 3e3;
68708
+ var CYCLE_FACTS_POLL_MS = 250;
68709
+ /** A closed run belongs to this finish when it ended within this much of it. */
68710
+ var CYCLE_RUN_MATCH_MS = 10 * 6e4;
68711
+ function factsOfClosed(run, finishedAtMs) {
68712
+ if (run.endedAt === null || Math.abs(run.endedAt - finishedAtMs) > CYCLE_RUN_MATCH_MS) return NC_UNKNOWN_CYCLE_FACTS;
68713
+ return {
68714
+ durationMs: run.durationMs,
68715
+ energyKwh: run.detail.energyKwh
68716
+ };
68717
+ }
68718
+ function applianceCycleFactsFromRuns(ports) {
68719
+ return async ({ deviceId, finishedAtMs }) => {
68720
+ let waited = 0;
68721
+ for (;;) {
68722
+ const run = await ports.newestRun(deviceId);
68723
+ if (run === null) return NC_UNKNOWN_CYCLE_FACTS;
68724
+ if (run.state === "closed") return factsOfClosed(run, finishedAtMs);
68725
+ if (run.startedAt > finishedAtMs) return NC_UNKNOWN_CYCLE_FACTS;
68726
+ if (waited >= CYCLE_FACTS_WAIT_MS) return {
68727
+ durationMs: finishedAtMs - run.startedAt,
68728
+ energyKwh: null
68729
+ };
68730
+ await ports.sleep(CYCLE_FACTS_POLL_MS);
68731
+ waited += CYCLE_FACTS_POLL_MS;
68732
+ }
68733
+ };
68734
+ }
68735
+ //#endregion
68611
68736
  //#region src/pipeline-analytics/runtime/wire-subscriptions.ts
68612
68737
  /**
68613
68738
  * Every category the Notification Center's system-event intake can turn into a
@@ -70569,6 +70694,8 @@ Object.freeze({
70569
70694
  "page": 1,
70570
70695
  "pageSize": 50
70571
70696
  } },
70697
+ "device-runs": { "listRuns": { "limit": 50 } },
70698
+ "fan-presets": { "capturePreset": { "steps": [] } },
70572
70699
  "llm": { "upsertProfile": { "profile": { "__nested__": {
70573
70700
  "timeoutMs": 6e4,
70574
70701
  "connectTimeoutMs": 1e4,
@@ -70809,6 +70936,10 @@ Object.freeze({
70809
70936
  "speed": 2
70810
70937
  }
70811
70938
  },
70939
+ "system": { "debugWatch": {
70940
+ "channels": [],
70941
+ "deviceIds": []
70942
+ } },
70812
70943
  "terminal-session": { "pullOutput": { "waitMs": 0 } },
70813
70944
  "training": {
70814
70945
  "planJob": { "selection": { "__nested__": { "workState": "complete" } } },
@@ -70855,6 +70986,7 @@ Object.freeze({
70855
70986
  ],
70856
70987
  "device-removal-hook": ["listDeviceData"],
70857
70988
  "failure-contribution": ["list"],
70989
+ "integration-instances": ["listInstances"],
70858
70990
  "llm": [
70859
70991
  "getDefaults",
70860
70992
  "getUsage",
@@ -70896,6 +71028,7 @@ Object.freeze({
70896
71028
  "listSupportedEntityKinds",
70897
71029
  "unexposeEntity"
70898
71030
  ],
71031
+ "integration-instances": ["testInstance"],
70899
71032
  "log-destination": [
70900
71033
  "cancelRead",
70901
71034
  "describeRead",
@@ -84994,6 +85127,9 @@ async function renderMosaic(request, logger) {
84994
85127
  * one composition are decisions about the set, and none of them belongs in a
84995
85128
  * shelf that photographs one camera for an absence.
84996
85129
  *
85130
+ * A SLEEPING battery camera is woken by one forced capture when the rule leaves
85131
+ * it allowed (D998) — bounded, once per gap per camera, never by a poll.
85132
+ *
84997
85133
  * Two reads can only ever ADD a camera back, never take one away on their own
84998
85134
  * failure (D49): a wrapper-state read (run in parallel with the capture) that
84999
85135
  * misses or throws keeps the tile, and a freshness read that misses or throws
@@ -85007,6 +85143,15 @@ var NC_LINKED_CAMERA_PREFIX = "nc-linked:";
85007
85143
  function isLinkedStillId(id) {
85008
85144
  return id.startsWith(NC_LINKED_MOSAIC_PREFIX) || id.startsWith(NC_LINKED_CAMERA_PREFIX);
85009
85145
  }
85146
+ /**
85147
+ * D998 — the one forced capture that wakes a sleeping battery camera for a
85148
+ * sensor notification: the bound it may take, the pause between re-polls of a
85149
+ * camera another wake already started, and the gap per camera before it is
85150
+ * woken again (a flapping contact must not drain a battery).
85151
+ */
85152
+ var NC_LINKED_WAKE_CAPTURE_TIMEOUT_MS = 15e3;
85153
+ var NC_LINKED_WAKE_POLL_MS = 1e3;
85154
+ var NC_LINKED_WAKE_MIN_GAP_MS = 6e4;
85010
85155
  /** Per camera — the marker's own bound (`SENSOR_MARKER_SNAPSHOT_TIMEOUT_MS`). */
85011
85156
  var SENSOR_LINKED_CAPTURE_TIMEOUT_MS = 2500;
85012
85157
  /** The capture-free wrapper-state read, per camera. It runs IN PARALLEL with
@@ -85039,11 +85184,14 @@ var NcLinkedStillShelf = class {
85039
85184
  deps;
85040
85185
  sets = /* @__PURE__ */ new Map();
85041
85186
  owners = /* @__PURE__ */ new Map();
85187
+ /** setId → when its in-flight wake gives up (the dispatcher waits that long). */
85188
+ pendingWakes = /* @__PURE__ */ new Map();
85189
+ lastWakeAt = /* @__PURE__ */ new Map();
85042
85190
  constructor(deps) {
85043
85191
  this.deps = deps;
85044
85192
  }
85045
85193
  /** SYNCHRONOUS: the evaluation that follows names these owners. */
85046
- captureSet(sensorId, cameraIds, atMs) {
85194
+ captureSet(sensorId, cameraIds, atMs, options = { wakeSleeping: false }) {
85047
85195
  const now = this.deps.now();
85048
85196
  this.prune(now);
85049
85197
  const setId = randomUUID();
@@ -85071,7 +85219,7 @@ var NcLinkedStillShelf = class {
85071
85219
  camera: cameraId
85072
85220
  });
85073
85221
  });
85074
- this.run(setId, stills, atMs, now).catch((err) => {
85222
+ this.run(setId, stills, atMs, now, options).catch((err) => {
85075
85223
  this.deps.logger.warn("sensor notification pictures failed — it ships text-only", {
85076
85224
  tags: { deviceId: sensorId },
85077
85225
  meta: { error: String(err) }
@@ -85079,6 +85227,15 @@ var NcLinkedStillShelf = class {
85079
85227
  });
85080
85228
  return stills;
85081
85229
  }
85230
+ /**
85231
+ * While a wake of one of this owner's cameras is in flight: the instant it
85232
+ * gives up (its bound plus one poll). `undefined` otherwise — the dispatcher
85233
+ * then keeps its ordinary still-wait.
85234
+ */
85235
+ pendingUntil(ownerId) {
85236
+ const ref = this.owners.get(ownerId);
85237
+ return ref === void 0 ? void 0 : this.pendingWakes.get(ref.setId);
85238
+ }
85082
85239
  /** `undefined` = not an owner this shelf minted (or pruned); `[]` = nothing (yet). */
85083
85240
  get(ownerId) {
85084
85241
  const ref = this.owners.get(ownerId);
@@ -85100,20 +85257,37 @@ var NcLinkedStillShelf = class {
85100
85257
  clear() {
85101
85258
  this.sets.clear();
85102
85259
  this.owners.clear();
85260
+ this.pendingWakes.clear();
85103
85261
  }
85104
- async run(setId, stills, atMs, startedAt) {
85105
- const results = await Promise.all(stills.cameraIds.map((id) => this.captureOne(id, startedAt)));
85262
+ async run(setId, stills, atMs, startedAt, options) {
85263
+ const ctx = {
85264
+ setId,
85265
+ sensorId: stills.sensorId,
85266
+ startedAt,
85267
+ options
85268
+ };
85269
+ let results;
85270
+ try {
85271
+ results = await Promise.all(stills.cameraIds.map((id) => this.captureOne(id, ctx)));
85272
+ } finally {
85273
+ this.pendingWakes.delete(setId);
85274
+ }
85106
85275
  const judged = await this.judgeFreshness(stills.sensorId, results, atMs);
85107
85276
  for (const r of judged) this.logTile(stills.sensorId, r);
85108
85277
  const landed = judged.filter(isLandedTile);
85109
85278
  const composed = await this.compose(stills.sensorId, landed, atMs);
85110
85279
  const undrawable = landed.length - composed.drawn;
85280
+ const woken = judged.filter((r) => r.woken === true).map((r) => r.cameraId);
85111
85281
  this.deps.logger.info(composed.mosaic.length === 0 ? "sensor notification has no linked picture — it ships text-only" : "sensor notification pictures ready", {
85112
85282
  tags: { deviceId: stills.sensorId },
85113
85283
  meta: {
85114
85284
  cameras: stills.cameraIds.length,
85115
85285
  landed: composed.drawn,
85116
85286
  ...undrawable > 0 ? { undrawable } : {},
85287
+ ...woken.length > 0 ? {
85288
+ woken,
85289
+ waitedMs: this.deps.now() - startedAt
85290
+ } : {},
85117
85291
  dropped: Object.fromEntries(judged.filter((r) => r.outcome !== "landed").map((r) => [String(r.cameraId), r.outcome])),
85118
85292
  tookMs: this.deps.now() - startedAt
85119
85293
  }
@@ -85126,21 +85300,25 @@ var NcLinkedStillShelf = class {
85126
85300
  mosaic: composed.mosaic
85127
85301
  });
85128
85302
  }
85129
- async captureOne(cameraId, startedAt) {
85130
- const took = () => this.deps.now() - startedAt;
85303
+ async captureOne(cameraId, ctx) {
85304
+ const took = () => this.deps.now() - ctx.startedAt;
85131
85305
  if (this.deps.isOnline(cameraId) === false) return {
85132
85306
  cameraId,
85133
85307
  outcome: "excluded",
85134
85308
  reason: "offline",
85135
85309
  tookMs: took()
85136
85310
  };
85137
- const [verdict, capture] = await Promise.all([this.wrapperVerdict(cameraId), this.captureStill(cameraId)]);
85138
- if (verdict.reason !== null) return {
85311
+ const [verdict, capture] = await Promise.all([this.wrapperVerdict(cameraId), this.captureStill(cameraId, false, SENSOR_LINKED_CAPTURE_TIMEOUT_MS)]);
85312
+ const excluded = (reason) => ({
85139
85313
  cameraId,
85140
85314
  outcome: "excluded",
85141
- reason: verdict.reason,
85315
+ reason,
85142
85316
  tookMs: took()
85143
- };
85317
+ });
85318
+ if (verdict.reason === "sleeping") return this.wakeOne(cameraId, ctx);
85319
+ if (verdict.reason === "waking" && ctx.options.wakeSleeping) return this.awaitWaking(cameraId, ctx);
85320
+ if (verdict.reason === "unreachable" && ctx.options.wakeSleeping) return excluded("wake-skipped:unreachable");
85321
+ if (verdict.reason !== null) return excluded(verdict.reason);
85144
85322
  return {
85145
85323
  cameraId,
85146
85324
  ...capture,
@@ -85148,9 +85326,84 @@ var NcLinkedStillShelf = class {
85148
85326
  tookMs: took()
85149
85327
  };
85150
85328
  }
85151
- async captureStill(cameraId) {
85329
+ /** D998: one forced capture, by the rule's leave, at most once per gap per camera. */
85330
+ async wakeOne(cameraId, ctx) {
85331
+ const took = () => this.deps.now() - ctx.startedAt;
85332
+ const skipped = (reason) => ({
85333
+ cameraId,
85334
+ outcome: "excluded",
85335
+ reason,
85336
+ tookMs: took()
85337
+ });
85338
+ if (!ctx.options.wakeSleeping) return skipped("wake-skipped:policy");
85339
+ const last = this.lastWakeAt.get(cameraId);
85340
+ if (last !== void 0 && ctx.startedAt - last < NC_LINKED_WAKE_MIN_GAP_MS) return skipped("wake-skipped:recent-wake");
85341
+ this.lastWakeAt.set(cameraId, ctx.startedAt);
85342
+ this.markPending(ctx);
85343
+ this.deps.logger.info("linked battery camera woken for the sensor notification", {
85344
+ tags: { deviceId: cameraId },
85345
+ meta: {
85346
+ sensorId: ctx.sensorId,
85347
+ ruleIds: ctx.options.ruleIds ?? [],
85348
+ boundMs: NC_LINKED_WAKE_CAPTURE_TIMEOUT_MS
85349
+ }
85350
+ });
85351
+ const capture = await this.captureStill(cameraId, true, NC_LINKED_WAKE_CAPTURE_TIMEOUT_MS);
85352
+ return {
85353
+ cameraId,
85354
+ ...this.asWakeResult(capture),
85355
+ woken: true,
85356
+ tookMs: took()
85357
+ };
85358
+ }
85359
+ /** A camera another wake already started: never forced, re-polled within the bound. */
85360
+ async awaitWaking(cameraId, ctx) {
85361
+ const took = () => this.deps.now() - ctx.startedAt;
85362
+ this.markPending(ctx);
85363
+ const polls = Math.floor(NC_LINKED_WAKE_CAPTURE_TIMEOUT_MS / NC_LINKED_WAKE_POLL_MS);
85364
+ for (let i = 0; i < polls; i++) {
85365
+ await new Promise((resolve) => setTimeout(resolve, NC_LINKED_WAKE_POLL_MS));
85366
+ const verdict = await this.wrapperVerdict(cameraId);
85367
+ if (verdict.reason === "waking") continue;
85368
+ if (verdict.reason !== null) return {
85369
+ cameraId,
85370
+ outcome: "excluded",
85371
+ reason: verdict.reason,
85372
+ tookMs: took()
85373
+ };
85374
+ const capture = await this.captureStill(cameraId, false, SENSOR_LINKED_CAPTURE_TIMEOUT_MS);
85375
+ return {
85376
+ cameraId,
85377
+ ...this.asWakeResult(capture),
85378
+ woken: true,
85379
+ tookMs: took()
85380
+ };
85381
+ }
85382
+ return {
85383
+ cameraId,
85384
+ outcome: "wake-timeout",
85385
+ woken: true,
85386
+ tookMs: took()
85387
+ };
85388
+ }
85389
+ markPending(ctx) {
85390
+ const until = ctx.startedAt + NC_LINKED_WAKE_CAPTURE_TIMEOUT_MS + NC_LINKED_WAKE_POLL_MS;
85391
+ this.pendingWakes.set(ctx.setId, Math.max(this.pendingWakes.get(ctx.setId) ?? 0, until));
85392
+ }
85393
+ /** A wake that brought nothing back names itself, not the generic `empty`. */
85394
+ asWakeResult(capture) {
85395
+ if (capture.outcome === "timeout") return {
85396
+ ...capture,
85397
+ outcome: "wake-timeout"
85398
+ };
85399
+ return capture.outcome === "empty" || capture.outcome === "error" && capture.reason !== "undecodable" ? {
85400
+ ...capture,
85401
+ outcome: "wake-refused"
85402
+ } : capture;
85403
+ }
85404
+ async captureStill(cameraId, force, timeoutMs) {
85152
85405
  try {
85153
- const shot = await withTimeout$2(this.deps.getSnapshot(cameraId), SENSOR_LINKED_CAPTURE_TIMEOUT_MS, "snapshot cap");
85406
+ const shot = await withTimeout$2(force ? this.deps.getSnapshot(cameraId, { force: true }) : this.deps.getSnapshot(cameraId), timeoutMs, "snapshot cap");
85154
85407
  if (shot === null || shot.base64.length === 0) return { outcome: "empty" };
85155
85408
  const jpeg = await this.decodableStill(Buffer.from(shot.base64, "base64"));
85156
85409
  if (jpeg === null) return {
@@ -86709,6 +86962,13 @@ var NC_RECORDED_FOOTAGE_WAIT_MS = 3e4;
86709
86962
  var NC_STILL_WAIT_MS = 3e3;
86710
86963
  var NC_STILL_WAIT_INTERVAL_MS = 500;
86711
86964
  /**
86965
+ * D998 — the longest a sensor notification holds for a linked battery camera
86966
+ * that is being woken (`stillDeadline`). A `sent` row is final, so the picture
86967
+ * cannot follow the push: it is waited for here, bounded, or never attached.
86968
+ * Owners with no wake in flight keep {@link NC_STILL_WAIT_MS}.
86969
+ */
86970
+ var NC_LINKED_WAKE_WAIT_MS = 15e3;
86971
+ /**
86712
86972
  * How far a still's OWN instant may sit from the trigger and still count as
86713
86973
  * being ABOUT the trigger, for a `delivery: 'immediate'` rule.
86714
86974
  *
@@ -87677,6 +87937,36 @@ var NcDispatcher = class {
87677
87937
  });
87678
87938
  }
87679
87939
  /**
87940
+ * The facts of a finished appliance cycle; unknown on every other row and on
87941
+ * any failure (a part that cannot be read is omitted, never a blocked send).
87942
+ */
87943
+ async applianceCycleFacts(entry) {
87944
+ const subject = entry.payload.subject;
87945
+ const resolve = this.deps.resolveApplianceCycleFacts;
87946
+ const deviceId = subject.applianceCycle?.deviceId;
87947
+ if (resolve === void 0 || deviceId === void 0) return NC_UNKNOWN_CYCLE_FACTS;
87948
+ try {
87949
+ const facts = await resolve({
87950
+ deviceId,
87951
+ finishedAtMs: subject.timestamp
87952
+ });
87953
+ if (facts.durationMs === null || facts.energyKwh === null) this.deps.logger.debug("appliance cycle part omitted — unknown", {
87954
+ tags: { deviceId },
87955
+ meta: {
87956
+ duration: facts.durationMs === null ? "unknown" : "known",
87957
+ energy: facts.energyKwh === null ? "unknown" : "known"
87958
+ }
87959
+ });
87960
+ return facts;
87961
+ } catch (err) {
87962
+ this.deps.logger.debug("appliance cycle facts failed — parts omitted", {
87963
+ tags: { deviceId },
87964
+ meta: { error: err instanceof Error ? err.message : String(err) }
87965
+ });
87966
+ return NC_UNKNOWN_CYCLE_FACTS;
87967
+ }
87968
+ }
87969
+ /**
87680
87970
  * Builds the notification AND returns the artefact ids its media resolve
87681
87971
  * indexed — see {@link withArtifactUrls}. A tuple rather than a field on
87682
87972
  * `NcNotificationInput`: the ids are internal (outbox provenance), never
@@ -87688,7 +87978,8 @@ var NcDispatcher = class {
87688
87978
  const deviceName = await notificationDeviceName(entry, this.deps.getDeviceName);
87689
87979
  const alarmSource = systemEvent?.alarmSource;
87690
87980
  const zoneLabels = systemEvent === void 0 ? await resolveZoneLabels(this.deps.getZoneNames, subject.deviceId, subject.zones) : alarmSource?.zones !== void 0 && alarmSource.zones.length > 0 ? await resolveZoneLabels(this.deps.getZoneNames, alarmSource.deviceId, alarmSource.zones) : [];
87691
- const vars = buildTemplateVars(this.texts, entry, deviceName, zoneLabels);
87981
+ const cycleFacts = await this.applianceCycleFacts(entry);
87982
+ const vars = buildTemplateVars(this.texts, entry, deviceName, zoneLabels, void 0, cycleFacts);
87692
87983
  this.warnDeprecatedVars(entry);
87693
87984
  const systemCount = systemEvent?.textCount !== void 0 ? { count: systemEvent.textCount } : {};
87694
87985
  const title = renderRowTitle(this.texts, entry, vars);
@@ -87894,7 +88185,15 @@ var NcDispatcher = class {
87894
88185
  const firstLook = groupTiles !== null ? null : await this.resolveAttachment(entry, canStillGainMedia(entry) ? "trigger-only" : "any");
87895
88186
  const footagePending = this.renderFootage(entry);
87896
88187
  const mosaic = groupView !== void 0 && groupTiles !== null ? await this.groupedMosaic(entry, groupView, groupTiles) : null;
87897
- const still = mosaic !== null ? mosaic.attachment : firstLook !== null || entry.payload.media === "none" ? firstLook : await this.waitForStill(entry);
88188
+ let waitedMs = 0;
88189
+ let still;
88190
+ if (mosaic !== null) still = mosaic.attachment;
88191
+ else if (firstLook !== null || entry.payload.media === "none") still = firstLook;
88192
+ else {
88193
+ const waited = await this.waitForStill(entry);
88194
+ still = waited.still;
88195
+ waitedMs = waited.waitedMs;
88196
+ }
87898
88197
  const grouped = groupView !== void 0 && groupMembers !== null ? {
87899
88198
  windowKey: groupView.key,
87900
88199
  members: groupView.members.length,
@@ -87919,6 +88218,7 @@ var NcDispatcher = class {
87919
88218
  recordKind: entry.recordKind,
87920
88219
  recordId: entry.recordId,
87921
88220
  policy: entry.payload.media,
88221
+ waitedMs,
87922
88222
  ...entry.payload.mediaImage !== void 0 ? { image: entry.payload.mediaImage } : {},
87923
88223
  ...memberTrackIds.length > 1 ? { memberTrackIds } : {},
87924
88224
  owners: [...entry.payload.subject.eventId !== void 0 ? [`object:${entry.payload.subject.eventId}`] : [], ...entry.payload.subject.trackId !== void 0 ? [`track:${entry.payload.subject.trackId}`] : []]
@@ -87945,7 +88245,13 @@ var NcDispatcher = class {
87945
88245
  const subject = entry.payload.subject;
87946
88246
  const out = [];
87947
88247
  for (const { ownerId, cameraId } of subject.extraStills ?? []) {
87948
- const file = await this.linkedStillFile(entry, ownerId, cameraId);
88248
+ let file = await this.linkedStillFile(entry, ownerId, cameraId);
88249
+ for (let polls = 0; file === void 0 && polls < NC_LINKED_WAKE_WAIT_MS / NC_STILL_WAIT_INTERVAL_MS; polls += 1) {
88250
+ const deadline = this.deps.stillDeadline?.(ownerId);
88251
+ if (deadline === void 0 || this.now() >= deadline) break;
88252
+ await this.sleep(NC_STILL_WAIT_INTERVAL_MS);
88253
+ file = await this.linkedStillFile(entry, ownerId, cameraId);
88254
+ }
87949
88255
  const bytes = file === void 0 ? null : decodeStillBytes(file.base64);
87950
88256
  if (file === void 0 || bytes === null) {
87951
88257
  this.deps.logger.info("linked camera picture missing at send — skipped", {
@@ -88432,11 +88738,19 @@ var NcDispatcher = class {
88432
88738
  */
88433
88739
  async waitForStill(entry) {
88434
88740
  const subject = entry.payload.subject;
88435
- if (this.now() - subject.timestamp > NC_STILL_WAIT_MAX_AGE_MS) return this.resolveAttachment(entry, "any");
88436
- if (subject.eventId === void 0 && subject.trackId === void 0) return null;
88437
- const attempts = Math.floor(NC_STILL_WAIT_MS / NC_STILL_WAIT_INTERVAL_MS);
88438
- for (let i = 0; i < attempts; i += 1) {
88741
+ if (this.now() - subject.timestamp > NC_STILL_WAIT_MAX_AGE_MS) return {
88742
+ still: await this.resolveAttachment(entry, "any"),
88743
+ waitedMs: 0
88744
+ };
88745
+ if (subject.eventId === void 0 && subject.trackId === void 0) return {
88746
+ still: null,
88747
+ waitedMs: 0
88748
+ };
88749
+ const startedAt = this.now();
88750
+ let waitedMs = 0;
88751
+ for (let i = 0; waitedMs < this.stillWaitBoundMs(entry, startedAt); i += 1) {
88439
88752
  await this.sleep(NC_STILL_WAIT_INTERVAL_MS);
88753
+ waitedMs += NC_STILL_WAIT_INTERVAL_MS;
88440
88754
  const still = await this.resolveAttachment(entry, "trigger-only");
88441
88755
  if (still !== null) {
88442
88756
  this.deps.logger.info("the still landed during the bounded wait", {
@@ -88448,10 +88762,32 @@ var NcDispatcher = class {
88448
88762
  kind: still.name
88449
88763
  }
88450
88764
  });
88451
- return still;
88765
+ return {
88766
+ still,
88767
+ waitedMs
88768
+ };
88452
88769
  }
88453
88770
  }
88454
- return this.resolveAttachment(entry, "any");
88771
+ return {
88772
+ still: await this.resolveAttachment(entry, "any"),
88773
+ waitedMs
88774
+ };
88775
+ }
88776
+ /**
88777
+ * How long this row's still poll may run: {@link NC_STILL_WAIT_MS}, or — while
88778
+ * the shelf says a linked camera of this row is being woken — until that
88779
+ * wake gives up, at most {@link NC_LINKED_WAKE_WAIT_MS} (D998).
88780
+ */
88781
+ stillWaitBoundMs(entry, startedAt) {
88782
+ const subject = entry.payload.subject;
88783
+ const owners = [...subject.trackId !== void 0 ? [subject.trackId] : [], ...(subject.extraStills ?? []).map((extra) => extra.ownerId)];
88784
+ let deadline;
88785
+ for (const ownerId of owners) {
88786
+ const until = this.deps.stillDeadline?.(ownerId);
88787
+ if (until !== void 0 && (deadline === void 0 || until > deadline)) deadline = until;
88788
+ }
88789
+ if (deadline === void 0) return NC_STILL_WAIT_MS;
88790
+ return Math.max(NC_STILL_WAIT_MS, Math.min(NC_LINKED_WAKE_WAIT_MS, deadline - startedAt));
88455
88791
  }
88456
88792
  /**
88457
88793
  * The grouped MOSAIC (D692 §6.2): one tile per member, at most
@@ -88599,8 +88935,8 @@ var NcDispatcher = class {
88599
88935
  return ts !== void 0 && this.now() - ts <= NC_STILL_WAIT_MAX_AGE_MS;
88600
88936
  });
88601
88937
  await look("trigger-only", pollable());
88602
- const attempts = Math.floor(NC_STILL_WAIT_MS / NC_STILL_WAIT_INTERVAL_MS);
88603
- for (let i = 0; i < attempts && pollable().length > 0; i += 1) {
88938
+ const startedAt = this.now();
88939
+ for (let waited = 0; waited < this.stillWaitBoundMs(entry, startedAt) && pollable().length > 0; waited += NC_STILL_WAIT_INTERVAL_MS) {
88604
88940
  await this.sleep(NC_STILL_WAIT_INTERVAL_MS);
88605
88941
  await look("trigger-only", pollable());
88606
88942
  }
@@ -88855,7 +89191,7 @@ function systemEventParamsForTemplate(params) {
88855
89191
  const { form: _form, attention: _attention, ...rest } = params;
88856
89192
  return rest;
88857
89193
  }
88858
- function buildTemplateVars(texts, entry, deviceName, zoneLabels, timeZone) {
89194
+ function buildTemplateVars(texts, entry, deviceName, zoneLabels, timeZone, cycle) {
88859
89195
  const subject = entry.payload.subject;
88860
89196
  const occupancy = subject.occupancy;
88861
89197
  const systemEvent = subject.systemEvent;
@@ -88891,6 +89227,7 @@ function buildTemplateVars(texts, entry, deviceName, zoneLabels, timeZone) {
88891
89227
  hitPercent: subject.audio?.hitPercent !== void 0 ? `${Math.round(subject.audio.hitPercent)}` : "",
88892
89228
  db: subject.audio?.peakDbfs !== void 0 ? `${Math.round(subject.audio.peakDbfs)}` : "",
88893
89229
  eventType: subject.eventType ?? "",
89230
+ ...cycle !== void 0 ? ncApplianceCycleVars(texts, cycle) : NC_EMPTY_CYCLE_VARS,
88894
89231
  rule: entry.payload.ruleName,
88895
89232
  count: occupancy !== void 0 ? `${occupancy.count}` : group !== void 0 && group.members.length > 1 ? `${group.members.length}` : "",
88896
89233
  capacity: occupancy !== void 0 ? `${occupancy.capacity}` : "",
@@ -88917,6 +89254,7 @@ function bodyKeyFor(entry) {
88917
89254
  const subject = entry.payload.subject;
88918
89255
  if (subject.systemEvent !== void 0) return subject.systemEvent.bodyKey ?? "";
88919
89256
  if (subject.occupancy !== void 0) return "occupancy.body";
89257
+ if (subject.applianceCycle !== void 0) return "appliance.finished.body";
88920
89258
  if (subject.packagePhase === "delivered" && subject.packagePossible === true) return "package.delivered.possible.body";
88921
89259
  if (subject.packagePhase !== void 0) return `package.${subject.packagePhase}.body`;
88922
89260
  return entry.recordKind === "track-end" ? "detection.body.trackEnd" : "detection.body";
@@ -88954,7 +89292,7 @@ function renderRowTitle(texts, entry, vars) {
88954
89292
  const systemEvent = entry.payload.subject.systemEvent;
88955
89293
  const intrusion = entry.payload.alarmIntrusion;
88956
89294
  const count = systemEvent?.textCount;
88957
- return renderRowText(texts, {
89295
+ const rendered = renderRowText(texts, {
88958
89296
  template: intrusion !== void 0 ? void 0 : entry.payload.template?.title,
88959
89297
  key: titleKeyFor(entry),
88960
89298
  vars: intrusion !== void 0 ? {
@@ -88964,11 +89302,13 @@ function renderRowTitle(texts, entry, vars) {
88964
89302
  ...count !== void 0 ? { count } : {},
88965
89303
  frozen: systemEvent?.title ?? entry.payload.ruleName
88966
89304
  });
89305
+ return titleKeyFor(entry) === "appliance.finished.title" && entry.payload.template?.title === void 0 ? ncSentenceCaseBody(rendered) : rendered;
88967
89306
  }
88968
89307
  /** The default TITLE key — same shape, same pre-catalog reasoning. */
88969
89308
  function titleKeyFor(entry) {
88970
89309
  const systemEvent = entry.payload.subject.systemEvent;
88971
89310
  if (systemEvent !== void 0) return systemEvent.titleKey ?? "";
89311
+ if (entry.payload.subject.applianceCycle !== void 0) return "appliance.finished.title";
88972
89312
  if (entry.payload.alarmIntrusion !== void 0) return "alarm.intrusion.title";
88973
89313
  const packagePhase = entry.payload.subject.packagePhase;
88974
89314
  if (packagePhase === "delivered" && entry.payload.subject.packagePossible === true) return "package.delivered.possible.title";
@@ -102040,6 +102380,7 @@ function buildEntries(host, rule, subject, kind, matchedOn, userTargets = [], or
102040
102380
  ...subject.audioWindow.peakDbfs !== void 0 ? { peakDbfs: subject.audioWindow.peakDbfs } : {}
102041
102381
  } } : {},
102042
102382
  ...subject.eventType !== void 0 ? { eventType: subject.eventType } : {},
102383
+ ...applianceCycleOf(subject),
102043
102384
  ...subject.systemEvent !== void 0 ? { systemEvent: subject.systemEvent } : {}
102044
102385
  }
102045
102386
  };
@@ -104115,7 +104456,7 @@ function beginLinkedStills(host, request) {
104115
104456
  if (rowCameraIds.length > 0 && rowShown.length === 0) return void 0;
104116
104457
  const shown = host.unmutedCameras(cameraIds);
104117
104458
  const involved = [sensorId, ...rowShown];
104118
- if (!host.rules.listEnabled("device-event").some((rule) => {
104459
+ const wanting = host.rules.listEnabled("device-event").filter((rule) => {
104119
104460
  if (ruleShipsNoStill(rule)) return false;
104120
104461
  if (!deviceEventRuleMayFireOnKind(rule, sensorKind, sensorRaised)) return false;
104121
104462
  const excluded = rule.conditions.devicesExclude;
@@ -104126,9 +104467,14 @@ function beginLinkedStills(host, request) {
104126
104467
  })) return false;
104127
104468
  const devices = rule.conditions.devices;
104128
104469
  return devices === void 0 || devices.length === 0 || devices.some((id) => involved.includes(id));
104129
- })) return void 0;
104470
+ });
104471
+ if (wanting.length === 0) return void 0;
104472
+ const wakeSleeping = wanting.some((rule) => rule.media?.wakeSleepingCamera !== false);
104130
104473
  for (const cameraId of cameraIds) if (!shown.includes(cameraId)) host.reportLinkedCameraMuted(cameraId, sensorId);
104131
- return shown.length > 0 ? shelf.captureSet(sensorId, shown, atMs) : void 0;
104474
+ return shown.length > 0 ? shelf.captureSet(sensorId, shown, atMs, {
104475
+ wakeSleeping,
104476
+ ruleIds: wanting.map((rule) => rule.id)
104477
+ }) : void 0;
104132
104478
  }
104133
104479
  /**
104134
104480
  * A muted camera left out of a linked set — one INFO line per camera per
@@ -106851,6 +107197,7 @@ var NotificationCenter = class {
106851
107197
  ...deps.dispatcher,
106852
107198
  logger: this.logger.child("dispatch"),
106853
107199
  texts: this.texts,
107200
+ stillDeadline: (ownerId) => isLinkedStillId(ownerId) ? this.linkedStills?.pendingUntil(ownerId) : void 0,
106854
107201
  getMediaForOwner: async (ownerKind, ownerId, eventScope) => {
106855
107202
  const held = isSyntheticId(ownerId) ? this.syntheticMedia.get(ownerId) : void 0;
106856
107203
  if (held !== void 0) return held.files;
@@ -109434,7 +109781,10 @@ var BuildNotificationCenter = class extends BuildNotificationCenterBase {
109434
109781
  },
109435
109782
  readAlerts: () => api.alerts.list.query({ limit: 5e3 }),
109436
109783
  emitBusEvent: (event) => this.ctx.eventBus.emit(event),
109437
- getSnapshot: (deviceId) => api.snapshot.getSnapshot.query({ deviceId }),
109784
+ getSnapshot: (deviceId, opts) => api.snapshot.getSnapshot.query(opts?.force === true ? {
109785
+ deviceId,
109786
+ force: true
109787
+ } : { deviceId }),
109438
109788
  recognitionOutlook: ({ deviceId, trackId, className, labelKind, now }) => recognitionOutlook({
109439
109789
  className,
109440
109790
  ...labelKind !== void 0 ? { labelKind } : {},
@@ -109777,6 +110127,7 @@ var BuildNotificationCenter = class extends BuildNotificationCenterBase {
109777
110127
  }));
109778
110128
  },
109779
110129
  getDeviceName,
110130
+ resolveApplianceCycleFacts: this.deps.resolveApplianceCycleFacts,
109780
110131
  getDeviceLocation,
109781
110132
  buildActions: (input) => this.notificationCenter?.mintButtons(input) ?? Promise.resolve([])
109782
110133
  },
@@ -123648,7 +123999,16 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
123648
123999
  buildTimelapsePorts: (api, stores) => this.buildTimelapsePorts(api, stores),
123649
124000
  buildSummaryPorts: (api, stores) => this.buildSummaryPorts(api, stores),
123650
124001
  wireAlarmPanel: (center) => this.wireAlarmPanel(center),
123651
- serveNcActionPlane: (center) => this.serveNcActionPlane(center)
124002
+ serveNcActionPlane: (center) => this.serveNcActionPlane(center),
124003
+ resolveApplianceCycleFacts: applianceCycleFactsFromRuns({
124004
+ newestRun: async (deviceId) => {
124005
+ return (await this.ctx.api.deviceRuns.listRuns.query({
124006
+ deviceId,
124007
+ limit: 1
124008
+ })).runs[0] ?? null;
124009
+ },
124010
+ sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms))
124011
+ })
123652
124012
  });
123653
124013
  return this.notificationCenterBootInstance;
123654
124014
  }