@camstack/addon-post-analysis 1.2.78 → 1.2.80
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/{dist-CFOT1Yoz.js → dist-BTbbBBpS.js} +227 -5
- package/dist/{dist-CA2KdMY9.mjs → dist-D9Z7czrz.mjs} +227 -5
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +1 -1
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DteUZxxp.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DHm8hb9G.mjs} +2 -2
- package/dist/pipeline-analytics/{_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-B4LMjxKe.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BeCNd7Q3.mjs} +1 -1
- package/dist/pipeline-analytics/{hostInit-BTue_6nN.mjs → hostInit-Dtf-oVL7.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +265 -55
- package/dist/pipeline-analytics/index.mjs +265 -55
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as string, B as addonWidgetsSourceCapability, C as NcSnoozeSchema, Ct as boolean, D as OpsLogEntrySchema, Dt as object, E as NcTaxonomySchema, Et as number, F as TIMELAPSE_DENSE_FLOOR_SEC, G as buildEventKindDescriptor, H as assertTimelapseCadences, I as TimelapseRuleInputSchema, J as defineCustomActions, K as cosineSimilarity$1, L as TimelapseRulePatchSchema, M as SCENE_DEFAULT_UNCOVERED_POLICY, Mt as EventCategory, N as SCENE_DIVERGED, O as RECORDING_EXPORT_MAX_READ_BYTES, Ot as partialRecord, P as SceneMonitorSchema, Q as faceGalleryCapability, R as TimelapseRuleSchema, S as NcSnoozeInputSchema, St as array, T as NcSystemEventKindSchema, Tt as literal, U as audioMetricsCapability, V as alarmPanelCapability, W as audioModeOf, Y as deriveRecordingMode, Z as encodeVectorBase64, _ as NcRuleInputSchema, _t as hydrateSchema, at as plateGalleryCapability, b as NcRuleTargetSchema, bt as sleep, c as EVENT_PAD_MS, ct as sceneMonitorCapability, d as NC_ALARM_SYSTEM_EVENT_KINDS, dt as videoclipsCapability, et as isDetectionMacroClass, f as NC_CONDITION_CATALOG, ft as zoneAnalyticsCapability, g as NcConditionDescriptorSchema, gt as createEvent, h as NC_TAXONOMY, ht as DeviceType, i as DETECTION_MACRO_CLASSES, it as pipelineAnalyticsCapability, j as SCENE_DEFAULT_ANCHOR_THRESHOLD, jt as unknown, k as RetrainStatusSchema, kt as record, l as LabelAttributionSchema, lt as subKindsOf, mt as BaseAddon, n as DEFAULT_EVENT_COLOR, nt as kebabToCamel, o as DeclaredDevices, ot as readDeviceStateFrom, p as NC_DEFAULT_SNOOZE_MINUTES, pt as errMsg, q as customAction, rt as notificationRulesCapability, s as EVENT_KIND_BY_CAP, st as readTimelapseGeneratedAt, t as BaseDevice, tt as isScheduleActive, u as MACRO_LABELS, ut as vectorDimFromBase64, v as NcRulePatchSchema, vt as isDeviceScopedCap, w as NcSnoozeSuppressedSchema, wt as discriminatedUnion, x as NcScheduleSchema, xt as _enum, y as NcRuleSchema, yt as nodePin, z as TrackSourceSchema } from "../dist-
|
|
1
|
+
import { At as string, B as addonWidgetsSourceCapability, C as NcSnoozeSchema, Ct as boolean, D as OpsLogEntrySchema, Dt as object, E as NcTaxonomySchema, Et as number, F as TIMELAPSE_DENSE_FLOOR_SEC, G as buildEventKindDescriptor, H as assertTimelapseCadences, I as TimelapseRuleInputSchema, J as defineCustomActions, K as cosineSimilarity$1, L as TimelapseRulePatchSchema, M as SCENE_DEFAULT_UNCOVERED_POLICY, Mt as EventCategory, N as SCENE_DIVERGED, O as RECORDING_EXPORT_MAX_READ_BYTES, Ot as partialRecord, P as SceneMonitorSchema, Q as faceGalleryCapability, R as TimelapseRuleSchema, S as NcSnoozeInputSchema, St as array, T as NcSystemEventKindSchema, Tt as literal, U as audioMetricsCapability, V as alarmPanelCapability, W as audioModeOf, Y as deriveRecordingMode, Z as encodeVectorBase64, _ as NcRuleInputSchema, _t as hydrateSchema, at as plateGalleryCapability, b as NcRuleTargetSchema, bt as sleep, c as EVENT_PAD_MS, ct as sceneMonitorCapability, d as NC_ALARM_SYSTEM_EVENT_KINDS, dt as videoclipsCapability, et as isDetectionMacroClass, f as NC_CONDITION_CATALOG, ft as zoneAnalyticsCapability, g as NcConditionDescriptorSchema, gt as createEvent, h as NC_TAXONOMY, ht as DeviceType, i as DETECTION_MACRO_CLASSES, it as pipelineAnalyticsCapability, j as SCENE_DEFAULT_ANCHOR_THRESHOLD, jt as unknown, k as RetrainStatusSchema, kt as record, l as LabelAttributionSchema, lt as subKindsOf, mt as BaseAddon, n as DEFAULT_EVENT_COLOR, nt as kebabToCamel, o as DeclaredDevices, ot as readDeviceStateFrom, p as NC_DEFAULT_SNOOZE_MINUTES, pt as errMsg, q as customAction, rt as notificationRulesCapability, s as EVENT_KIND_BY_CAP, st as readTimelapseGeneratedAt, t as BaseDevice, tt as isScheduleActive, u as MACRO_LABELS, ut as vectorDimFromBase64, v as NcRulePatchSchema, vt as isDeviceScopedCap, w as NcSnoozeSuppressedSchema, wt as discriminatedUnion, x as NcScheduleSchema, xt as _enum, y as NcRuleSchema, yt as nodePin, z as TrackSourceSchema } from "../dist-D9Z7czrz.mjs";
|
|
2
2
|
import { t as __exportAll } from "../embedding-encoder/index.mjs";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import { promises } from "node:fs";
|
|
@@ -14138,12 +14138,15 @@ function dwellSeconds(candidate) {
|
|
|
14138
14138
|
* branch that discards work silently reads as "it never happened".
|
|
14139
14139
|
*/
|
|
14140
14140
|
function filterSummaryCandidates(candidates, filters, zoneOwner) {
|
|
14141
|
+
const moving = filters?.includeStationary === true ? candidates : candidates.filter((candidate) => candidate.stationary !== true);
|
|
14142
|
+
const droppedStationary = candidates.length - moving.length;
|
|
14141
14143
|
if (filters === void 0) return {
|
|
14142
|
-
kept: [...
|
|
14144
|
+
kept: [...moving],
|
|
14143
14145
|
droppedByClass: 0,
|
|
14144
14146
|
droppedByZone: 0,
|
|
14145
14147
|
droppedByImportance: 0,
|
|
14146
|
-
droppedByDwell: 0
|
|
14148
|
+
droppedByDwell: 0,
|
|
14149
|
+
droppedStationary
|
|
14147
14150
|
};
|
|
14148
14151
|
const include = filters.classes;
|
|
14149
14152
|
const exclude = new Set(filters.classesExclude ?? []);
|
|
@@ -14152,7 +14155,7 @@ function filterSummaryCandidates(candidates, filters, zoneOwner) {
|
|
|
14152
14155
|
let droppedByZone = 0;
|
|
14153
14156
|
let droppedByImportance = 0;
|
|
14154
14157
|
let droppedByDwell = 0;
|
|
14155
|
-
for (const candidate of
|
|
14158
|
+
for (const candidate of moving) {
|
|
14156
14159
|
const own = classesOf(candidate);
|
|
14157
14160
|
if (own.some((c) => exclude.has(c))) {
|
|
14158
14161
|
droppedByClass += 1;
|
|
@@ -14188,7 +14191,8 @@ function filterSummaryCandidates(candidates, filters, zoneOwner) {
|
|
|
14188
14191
|
droppedByClass,
|
|
14189
14192
|
droppedByZone,
|
|
14190
14193
|
droppedByImportance,
|
|
14191
|
-
droppedByDwell
|
|
14194
|
+
droppedByDwell,
|
|
14195
|
+
droppedStationary
|
|
14192
14196
|
};
|
|
14193
14197
|
}
|
|
14194
14198
|
/**
|
|
@@ -14563,7 +14567,8 @@ var NcSummaryProducer = class {
|
|
|
14563
14567
|
droppedByClass: filtered.droppedByClass,
|
|
14564
14568
|
droppedByZone: filtered.droppedByZone,
|
|
14565
14569
|
droppedByImportance: filtered.droppedByImportance,
|
|
14566
|
-
droppedByDwell: filtered.droppedByDwell
|
|
14570
|
+
droppedByDwell: filtered.droppedByDwell,
|
|
14571
|
+
droppedStationary: filtered.droppedStationary
|
|
14567
14572
|
} });
|
|
14568
14573
|
if (opts.stamp) await this.deps.store.markGenerated(rule.id, window.endMs);
|
|
14569
14574
|
return {
|
|
@@ -14571,7 +14576,8 @@ var NcSummaryProducer = class {
|
|
|
14571
14576
|
window,
|
|
14572
14577
|
tiles: 0,
|
|
14573
14578
|
cameras: 0,
|
|
14574
|
-
matched: 0
|
|
14579
|
+
matched: 0,
|
|
14580
|
+
droppedStationary: filtered.droppedStationary
|
|
14575
14581
|
};
|
|
14576
14582
|
}
|
|
14577
14583
|
const loaded = await this.loadTiles(rule, selection.tiles);
|
|
@@ -14594,6 +14600,7 @@ var NcSummaryProducer = class {
|
|
|
14594
14600
|
produced: 0,
|
|
14595
14601
|
window,
|
|
14596
14602
|
tiles: loaded.length,
|
|
14603
|
+
droppedStationary: filtered.droppedStationary,
|
|
14597
14604
|
skippedByAi: true,
|
|
14598
14605
|
...ai.aiFailure !== void 0 ? { aiFailure: ai.aiFailure } : {},
|
|
14599
14606
|
...ai.aiImages !== void 0 ? { aiImages: ai.aiImages } : {}
|
|
@@ -14624,6 +14631,8 @@ var NcSummaryProducer = class {
|
|
|
14624
14631
|
...meta,
|
|
14625
14632
|
scanned: candidates.length,
|
|
14626
14633
|
matched: filtered.kept.length,
|
|
14634
|
+
droppedStationary: filtered.droppedStationary,
|
|
14635
|
+
droppedByClass: filtered.droppedByClass,
|
|
14627
14636
|
tiles: loaded.length,
|
|
14628
14637
|
cameras: new Set(loaded.map((t) => t.candidate.deviceId)).size,
|
|
14629
14638
|
camerasDropped: selection.camerasDropped,
|
|
@@ -14642,6 +14651,7 @@ var NcSummaryProducer = class {
|
|
|
14642
14651
|
tiles: loaded.length,
|
|
14643
14652
|
cameras: new Set(loaded.map((t) => t.candidate.deviceId)).size,
|
|
14644
14653
|
matched: filtered.kept.length,
|
|
14654
|
+
droppedStationary: filtered.droppedStationary,
|
|
14645
14655
|
enqueued,
|
|
14646
14656
|
...mosaic.bytes > 0 ? { mosaicBytes: mosaic.bytes } : {},
|
|
14647
14657
|
...mosaic.ref !== null ? { mosaicUrl: mosaic.ref.url } : {},
|
|
@@ -15014,7 +15024,26 @@ var NcSummaryFiltersSchema = object({
|
|
|
15014
15024
|
classesExclude: array(string().min(1).max(40)).max(20).optional(),
|
|
15015
15025
|
zones: array(string()).max(40).optional(),
|
|
15016
15026
|
minImportance: number().min(0).max(1).optional(),
|
|
15017
|
-
minDwellSeconds: number().min(0).max(3600).optional()
|
|
15027
|
+
minDwellSeconds: number().min(0).max(3600).optional(),
|
|
15028
|
+
/**
|
|
15029
|
+
* Put PARKED objects in the digest too. Off unless explicitly turned on, and
|
|
15030
|
+
* an ABSENT field reads as off — the soft migration, no backfill.
|
|
15031
|
+
*
|
|
15032
|
+
* A digest is a record of PASSAGES: the operator's words are "the last
|
|
15033
|
+
* summaries still include an enormous number of stationary tracks". Since
|
|
15034
|
+
* D161 a track promoted to the stationary registry is persisted rather than
|
|
15035
|
+
* dropped (it owns media the retention sweep has to reach), so the car parked
|
|
15036
|
+
* in front of camera 617 now enters every window it overlaps and, ranked on
|
|
15037
|
+
* importance and dwell, wins tiles from the passages the digest is about. The
|
|
15038
|
+
* measured effect on the live hub was 1-2 tiles becoming 10.
|
|
15039
|
+
*
|
|
15040
|
+
* `.optional()` and NOT `.default(false)`: a `.default()` here would be
|
|
15041
|
+
* materialised by `NcSummaryRulePatchSchema` on any patch that named
|
|
15042
|
+
* `filters`, which is the `.partial()` trap this module's docblock describes.
|
|
15043
|
+
* `filterSummaryCandidates` reads `=== true`, so absent and false are the
|
|
15044
|
+
* same answer and neither needs a stored value.
|
|
15045
|
+
*/
|
|
15046
|
+
includeStationary: boolean().optional()
|
|
15018
15047
|
});
|
|
15019
15048
|
/**
|
|
15020
15049
|
* How tiles are chosen when the window holds more tracks than the budget.
|
|
@@ -21798,6 +21827,14 @@ var ncActions = defineCustomActions({
|
|
|
21798
21827
|
tiles: number().int().optional(),
|
|
21799
21828
|
cameras: number().int().optional(),
|
|
21800
21829
|
matched: number().int().optional(),
|
|
21830
|
+
/**
|
|
21831
|
+
* PARKED objects the window held and the rule dropped (`filters
|
|
21832
|
+
* .includeStationary`). Without it a Test that returns two tiles out of
|
|
21833
|
+
* forty tracks cannot tell the operator whether the night was quiet or
|
|
21834
|
+
* whether it was the car park — and that is the exact question this
|
|
21835
|
+
* option exists to answer.
|
|
21836
|
+
*/
|
|
21837
|
+
droppedStationary: number().int().optional(),
|
|
21801
21838
|
enqueued: number().int().optional(),
|
|
21802
21839
|
mosaicBytes: number().int().optional(),
|
|
21803
21840
|
mosaicUrl: string().optional(),
|
|
@@ -22264,6 +22301,7 @@ function makeNcActionHandlers(deps) {
|
|
|
22264
22301
|
...out.tiles !== void 0 ? { tiles: out.tiles } : {},
|
|
22265
22302
|
...out.cameras !== void 0 ? { cameras: out.cameras } : {},
|
|
22266
22303
|
...out.matched !== void 0 ? { matched: out.matched } : {},
|
|
22304
|
+
...out.droppedStationary !== void 0 ? { droppedStationary: out.droppedStationary } : {},
|
|
22267
22305
|
...out.enqueued !== void 0 ? { enqueued: out.enqueued } : {},
|
|
22268
22306
|
...out.mosaicBytes !== void 0 ? { mosaicBytes: out.mosaicBytes } : {},
|
|
22269
22307
|
...out.mosaicUrl !== void 0 ? { mosaicUrl: out.mosaicUrl } : {},
|
|
@@ -26267,7 +26305,9 @@ var FrameProcessor = class {
|
|
|
26267
26305
|
}) : {
|
|
26268
26306
|
suppressedIndices: /* @__PURE__ */ new Set(),
|
|
26269
26307
|
confirmed: [],
|
|
26270
|
-
wokenEntryIds: []
|
|
26308
|
+
wokenEntryIds: [],
|
|
26309
|
+
armedEntryIds: [],
|
|
26310
|
+
disarmedEntryIds: []
|
|
26271
26311
|
};
|
|
26272
26312
|
const trackerInput = gate.suppressedIndices.size > 0 ? filteredDetections.filter((_, i) => !gate.suppressedIndices.has(i)) : filteredDetections;
|
|
26273
26313
|
const trackedDetections = this.tracker.update(trackerInput, timestamp, {
|
|
@@ -26477,6 +26517,8 @@ var FrameProcessor = class {
|
|
|
26477
26517
|
rawTrackedDetections: trackedDetections,
|
|
26478
26518
|
stationaryConfirmed: gate.confirmed,
|
|
26479
26519
|
stationaryWoken: gate.wokenEntryIds,
|
|
26520
|
+
stationaryArmed: gate.armedEntryIds,
|
|
26521
|
+
stationaryDisarmed: gate.disarmedEntryIds,
|
|
26480
26522
|
riderFolds
|
|
26481
26523
|
};
|
|
26482
26524
|
}
|
|
@@ -36004,20 +36046,38 @@ function centroidInside(b, p) {
|
|
|
36004
36046
|
* box → SUPPRESS (detector box jitter — the box shrank/grew around the same
|
|
36005
36047
|
* centre; still the parked object, must not spawn a duplicate track).
|
|
36006
36048
|
* - `wakeAssocIou` ≤ best IoU < `suppressIou`, centroid OUTSIDE the parked box
|
|
36007
|
-
* →
|
|
36008
|
-
* suppressed, so it spawns a fresh moving track.
|
|
36049
|
+
* → DEPARTING (the object's box slid off its spot).
|
|
36009
36050
|
* - best IoU < `wakeAssocIou` → MISS: no detection overlaps this entry (a
|
|
36010
|
-
* different object, or the parked object is momentarily undetected).
|
|
36011
|
-
*
|
|
36051
|
+
* different object, or the parked object is momentarily undetected). The TTL
|
|
36052
|
+
* sweep retires it only if the absence persists.
|
|
36053
|
+
*
|
|
36054
|
+
* ## A departure is never acted on from ONE read (D49)
|
|
36055
|
+
*
|
|
36056
|
+
* Retiring an entry DESTROYS work: the object's registry identity, and with it
|
|
36057
|
+
* the suppression that stops it re-spawning a track every 30 s. So a single
|
|
36058
|
+
* departing read only ARMS the entry — the detection is still suppressed and
|
|
36059
|
+
* the entry survives. The entry is retired only when a SECOND read agrees:
|
|
36060
|
+
* departing again, or missing entirely (the object really has left the spot).
|
|
36061
|
+
* A confirming read DISARMS it.
|
|
36062
|
+
*
|
|
36063
|
+
* The caller owns the armed set and passes it back in; this function stays
|
|
36064
|
+
* pure. Cost of the extra read: a genuinely departing object spawns its track
|
|
36065
|
+
* one frame later. Cost of NOT having it, measured on the live hub over 24 h:
|
|
36066
|
+
* 65% of all stationary entries were retired within 300 s — below the TTL, so
|
|
36067
|
+
* by a wake — and 38% of the tracks that promotion then re-created had never
|
|
36068
|
+
* moved in their entire life. One bad box per parked object was enough.
|
|
36012
36069
|
*
|
|
36013
36070
|
* A detection can suppress at most one spawn even if it overlaps two entries
|
|
36014
36071
|
* (`suppressedIndices` is a set).
|
|
36015
36072
|
*/
|
|
36016
36073
|
function partitionDetectionsAgainstRegistry(input) {
|
|
36017
36074
|
const { entries, detections, config } = input;
|
|
36075
|
+
const armed = input.armedEntryIds ?? EMPTY_ARMED;
|
|
36018
36076
|
const suppressed = /* @__PURE__ */ new Set();
|
|
36019
36077
|
const confirmed = [];
|
|
36020
36078
|
const woken = [];
|
|
36079
|
+
const toArm = [];
|
|
36080
|
+
const toDisarm = [];
|
|
36021
36081
|
for (const entry of entries) {
|
|
36022
36082
|
let bestIou = 0;
|
|
36023
36083
|
let bestIdx = -1;
|
|
@@ -36030,23 +36090,37 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
36030
36090
|
bestIdx = di;
|
|
36031
36091
|
}
|
|
36032
36092
|
}
|
|
36033
|
-
if (bestIdx < 0 || bestIou < config.wakeAssocIou)
|
|
36093
|
+
if (bestIdx < 0 || bestIou < config.wakeAssocIou) {
|
|
36094
|
+
if (armed.has(entry.id)) woken.push(entry.id);
|
|
36095
|
+
continue;
|
|
36096
|
+
}
|
|
36034
36097
|
const detCentroid = centroid(detections[bestIdx].bbox);
|
|
36035
|
-
|
|
36098
|
+
const strong = bestIou >= config.suppressIou;
|
|
36099
|
+
if (strong || centroidInside(entry.bbox, detCentroid)) {
|
|
36036
36100
|
suppressed.add(bestIdx);
|
|
36037
36101
|
confirmed.push({
|
|
36038
36102
|
entryId: entry.id,
|
|
36039
36103
|
className: entry.className,
|
|
36040
|
-
bbox: { ...entry.bbox }
|
|
36104
|
+
bbox: { ...entry.bbox },
|
|
36105
|
+
observedBbox: { ...detections[bestIdx].bbox },
|
|
36106
|
+
strong
|
|
36041
36107
|
});
|
|
36042
|
-
|
|
36108
|
+
if (armed.has(entry.id)) toDisarm.push(entry.id);
|
|
36109
|
+
} else if (armed.has(entry.id)) woken.push(entry.id);
|
|
36110
|
+
else {
|
|
36111
|
+
toArm.push(entry.id);
|
|
36112
|
+
suppressed.add(bestIdx);
|
|
36113
|
+
}
|
|
36043
36114
|
}
|
|
36044
36115
|
return {
|
|
36045
36116
|
suppressedIndices: suppressed,
|
|
36046
36117
|
confirmed,
|
|
36047
|
-
wokenEntryIds: woken
|
|
36118
|
+
wokenEntryIds: woken,
|
|
36119
|
+
armedEntryIds: toArm,
|
|
36120
|
+
disarmedEntryIds: toDisarm
|
|
36048
36121
|
};
|
|
36049
36122
|
}
|
|
36123
|
+
var EMPTY_ARMED = /* @__PURE__ */ new Set();
|
|
36050
36124
|
/**
|
|
36051
36125
|
* A track is promoted when, over the recent `windowMs`, its centroid barely
|
|
36052
36126
|
* moved (both net displacement and path span below the static thresholds) AND
|
|
@@ -36619,6 +36693,21 @@ var StationaryObjectRegistry = class {
|
|
|
36619
36693
|
* between motion sessions; that silence is not evidence the object left,
|
|
36620
36694
|
* so quiet minutes must not age the entries (see {@link sweep}). */
|
|
36621
36695
|
lastFrameAtByDevice = /* @__PURE__ */ new Map();
|
|
36696
|
+
/**
|
|
36697
|
+
* Entries carrying ONE unconfirmed departure read, per device (D49, D174).
|
|
36698
|
+
*
|
|
36699
|
+
* Retiring an entry destroys work — the object's registry identity and the
|
|
36700
|
+
* suppression that keeps it from re-spawning a track every promotion window.
|
|
36701
|
+
* A single frame whose box slid off the parked spot is a fallible read (a
|
|
36702
|
+
* partial occlusion, a shadow, one bad box), so it only ARMS the entry here.
|
|
36703
|
+
* The retirement happens on the next frame that AGREES; a confirming frame
|
|
36704
|
+
* clears the strike.
|
|
36705
|
+
*/
|
|
36706
|
+
departureStrikes = /* @__PURE__ */ new Map();
|
|
36707
|
+
/** Detections absorbed by an existing entry since the last sweep, per device.
|
|
36708
|
+
* Rolled up into ONE log line per sweep — this fires on every frame of every
|
|
36709
|
+
* parked object, so it can never be a line of its own. */
|
|
36710
|
+
absorbedSinceSweep = /* @__PURE__ */ new Map();
|
|
36622
36711
|
constructor(deps) {
|
|
36623
36712
|
this.logger = deps.logger;
|
|
36624
36713
|
this.ledger = new DurableLedger({
|
|
@@ -36691,12 +36780,15 @@ var StationaryObjectRegistry = class {
|
|
|
36691
36780
|
if (entries.length === 0) return {
|
|
36692
36781
|
suppressedIndices: /* @__PURE__ */ new Set(),
|
|
36693
36782
|
confirmed: [],
|
|
36694
|
-
wokenEntryIds: []
|
|
36783
|
+
wokenEntryIds: [],
|
|
36784
|
+
armedEntryIds: [],
|
|
36785
|
+
disarmedEntryIds: []
|
|
36695
36786
|
};
|
|
36696
36787
|
return partitionDetectionsAgainstRegistry({
|
|
36697
36788
|
entries,
|
|
36698
36789
|
detections: input.detections,
|
|
36699
|
-
config: config ?? this.matchConfig
|
|
36790
|
+
config: config ?? this.matchConfig,
|
|
36791
|
+
...this.departureStrikes.has(input.deviceId) ? { armedEntryIds: this.departureStrikes.get(input.deviceId) } : {}
|
|
36700
36792
|
});
|
|
36701
36793
|
}
|
|
36702
36794
|
/** Fold a frame's gate result back into state: advance confirmed entries'
|
|
@@ -36713,15 +36805,41 @@ var StationaryObjectRegistry = class {
|
|
|
36713
36805
|
if (!e) continue;
|
|
36714
36806
|
this.ledger.stage({
|
|
36715
36807
|
...e,
|
|
36716
|
-
lastConfirmedAt: input.timestamp
|
|
36808
|
+
lastConfirmedAt: input.timestamp,
|
|
36809
|
+
...c.strong ? { bbox: { ...c.observedBbox } } : {}
|
|
36717
36810
|
});
|
|
36718
36811
|
this.dirty.add(c.entryId);
|
|
36719
36812
|
}
|
|
36813
|
+
this.absorbedSinceSweep.set(input.deviceId, (this.absorbedSinceSweep.get(input.deviceId) ?? 0) + input.confirmed.length);
|
|
36814
|
+
if (input.armedEntryIds && input.armedEntryIds.length > 0) {
|
|
36815
|
+
let armed = this.departureStrikes.get(input.deviceId);
|
|
36816
|
+
if (!armed) {
|
|
36817
|
+
armed = /* @__PURE__ */ new Set();
|
|
36818
|
+
this.departureStrikes.set(input.deviceId, armed);
|
|
36819
|
+
}
|
|
36820
|
+
for (const id of input.armedEntryIds) if (ids.has(id)) armed.add(id);
|
|
36821
|
+
}
|
|
36822
|
+
const armed = this.departureStrikes.get(input.deviceId);
|
|
36823
|
+
if (armed && input.disarmedEntryIds) {
|
|
36824
|
+
for (const id of input.disarmedEntryIds) armed.delete(id);
|
|
36825
|
+
if (armed.size === 0) this.departureStrikes.delete(input.deviceId);
|
|
36826
|
+
}
|
|
36720
36827
|
for (const id of input.wokenEntryIds) {
|
|
36721
36828
|
if (!ids.has(id)) continue;
|
|
36722
36829
|
const e = this.ledger.get(id);
|
|
36723
36830
|
if (!e) continue;
|
|
36724
36831
|
this.dropEntry(input.deviceId, id);
|
|
36832
|
+
this.logger.info("stationary entry retired", {
|
|
36833
|
+
tags: { deviceId: input.deviceId },
|
|
36834
|
+
meta: {
|
|
36835
|
+
deviceId: input.deviceId,
|
|
36836
|
+
entryId: id,
|
|
36837
|
+
className: e.className,
|
|
36838
|
+
reason: "departed",
|
|
36839
|
+
parkedForMs: input.timestamp - e.becameStationaryAt,
|
|
36840
|
+
...e.sourceTrackId !== void 0 ? { sourceTrackId: e.sourceTrackId } : {}
|
|
36841
|
+
}
|
|
36842
|
+
});
|
|
36725
36843
|
this.onChange?.({
|
|
36726
36844
|
phase: "departed",
|
|
36727
36845
|
entry: e,
|
|
@@ -36768,6 +36886,18 @@ var StationaryObjectRegistry = class {
|
|
|
36768
36886
|
if (observedAt - e.lastConfirmedAt > ttl) {
|
|
36769
36887
|
this.dropEntry(deviceId, id);
|
|
36770
36888
|
retired.push(e);
|
|
36889
|
+
this.logger.info("stationary entry retired", {
|
|
36890
|
+
tags: { deviceId },
|
|
36891
|
+
meta: {
|
|
36892
|
+
deviceId,
|
|
36893
|
+
entryId: id,
|
|
36894
|
+
className: e.className,
|
|
36895
|
+
reason: "ttl",
|
|
36896
|
+
ttlMs: ttl,
|
|
36897
|
+
unconfirmedForMs: observedAt - e.lastConfirmedAt,
|
|
36898
|
+
parkedForMs: observedAt - e.becameStationaryAt
|
|
36899
|
+
}
|
|
36900
|
+
});
|
|
36771
36901
|
this.onChange?.({
|
|
36772
36902
|
phase: "departed",
|
|
36773
36903
|
entry: e,
|
|
@@ -36777,6 +36907,18 @@ var StationaryObjectRegistry = class {
|
|
|
36777
36907
|
}
|
|
36778
36908
|
if (ids.size === 0) this.idsByDevice.delete(deviceId);
|
|
36779
36909
|
}
|
|
36910
|
+
for (const [deviceId, absorbed] of this.absorbedSinceSweep) {
|
|
36911
|
+
if (absorbed === 0) continue;
|
|
36912
|
+
this.logger.info("stationary registry absorbed detections", {
|
|
36913
|
+
tags: { deviceId },
|
|
36914
|
+
meta: {
|
|
36915
|
+
deviceId,
|
|
36916
|
+
absorbed,
|
|
36917
|
+
entries: this.count(deviceId)
|
|
36918
|
+
}
|
|
36919
|
+
});
|
|
36920
|
+
}
|
|
36921
|
+
this.absorbedSinceSweep.clear();
|
|
36780
36922
|
for (const id of [...this.dirty]) {
|
|
36781
36923
|
this.dirty.delete(id);
|
|
36782
36924
|
const entry = this.ledger.get(id);
|
|
@@ -36789,6 +36931,8 @@ var StationaryObjectRegistry = class {
|
|
|
36789
36931
|
* Used on device unbind; a rebind reloads from the store. */
|
|
36790
36932
|
forgetDevice(deviceId) {
|
|
36791
36933
|
this.lastFrameAtByDevice.delete(deviceId);
|
|
36934
|
+
this.departureStrikes.delete(deviceId);
|
|
36935
|
+
this.absorbedSinceSweep.delete(deviceId);
|
|
36792
36936
|
const ids = this.idsByDevice.get(deviceId);
|
|
36793
36937
|
if (!ids) return;
|
|
36794
36938
|
for (const id of ids) {
|
|
@@ -36800,6 +36944,8 @@ var StationaryObjectRegistry = class {
|
|
|
36800
36944
|
/** Delete every persisted + in-memory entry for a device (operator wipe). */
|
|
36801
36945
|
async clearDevice(deviceId) {
|
|
36802
36946
|
this.lastFrameAtByDevice.delete(deviceId);
|
|
36947
|
+
this.departureStrikes.delete(deviceId);
|
|
36948
|
+
this.absorbedSinceSweep.delete(deviceId);
|
|
36803
36949
|
const ids = this.idsByDevice.get(deviceId);
|
|
36804
36950
|
if (ids) {
|
|
36805
36951
|
for (const id of [...ids]) {
|
|
@@ -36817,10 +36963,17 @@ var StationaryObjectRegistry = class {
|
|
|
36817
36963
|
}
|
|
36818
36964
|
set.add(id);
|
|
36819
36965
|
}
|
|
36820
|
-
/** Retire one entry: index, staged advance and durable row
|
|
36966
|
+
/** Retire one entry: index, staged advance, pending strike and durable row
|
|
36967
|
+
* all go. A strike that outlived its entry would arm the NEXT entry to reuse
|
|
36968
|
+
* the id — the registry mints UUIDs, but the invariant is cheap to keep. */
|
|
36821
36969
|
dropEntry(deviceId, id) {
|
|
36822
36970
|
this.idsByDevice.get(deviceId)?.delete(id);
|
|
36823
36971
|
this.dirty.delete(id);
|
|
36972
|
+
const armed = this.departureStrikes.get(deviceId);
|
|
36973
|
+
if (armed) {
|
|
36974
|
+
armed.delete(id);
|
|
36975
|
+
if (armed.size === 0) this.departureStrikes.delete(deviceId);
|
|
36976
|
+
}
|
|
36824
36977
|
this.ledger.forget(id);
|
|
36825
36978
|
}
|
|
36826
36979
|
};
|
|
@@ -40864,6 +41017,26 @@ function isAfterCursor(row, cursor) {
|
|
|
40864
41017
|
}
|
|
40865
41018
|
//#endregion
|
|
40866
41019
|
//#region src/pipeline-analytics/store/track-store.ts
|
|
41020
|
+
/**
|
|
41021
|
+
* WHY a track's row was written EARLY — i.e. by {@link TrackStore.closeActive}
|
|
41022
|
+
* rather than by the ordinary TTL expiry.
|
|
41023
|
+
*
|
|
41024
|
+
* `'stationary-promotion'` is the only member and means: the tracker decided
|
|
41025
|
+
* this subject had PARKED, handed it to the stationary registry, and the row
|
|
41026
|
+
* was written so its media, events and vector keep an owner (D161). It is not a
|
|
41027
|
+
* quality signal and it never hides the track — a parked car is still a track,
|
|
41028
|
+
* still on the events page, still swept by the same retention. It exists so a
|
|
41029
|
+
* consumer that wants PASSAGES can say so exactly, instead of re-deriving
|
|
41030
|
+
* "did it move" from a trajectory downstream and getting it wrong on the
|
|
41031
|
+
* subject that stood still for one honest reason.
|
|
41032
|
+
*
|
|
41033
|
+
* An ABSENT value means "expired normally, or written before this marker
|
|
41034
|
+
* existed". Never read an absence as a positive — same rule as `hasFace`.
|
|
41035
|
+
*/
|
|
41036
|
+
var TRACK_CLOSE_REASONS = ["stationary-promotion"];
|
|
41037
|
+
function parseCloseReason(value) {
|
|
41038
|
+
return TRACK_CLOSE_REASONS.find((reason) => reason === value);
|
|
41039
|
+
}
|
|
40867
41040
|
var DEFAULT_CONFIG = {
|
|
40868
41041
|
ttlMs: 3e4,
|
|
40869
41042
|
maxPositionHistory: 300
|
|
@@ -41086,6 +41259,10 @@ var TRACKS_COLUMNS = [
|
|
|
41086
41259
|
{
|
|
41087
41260
|
name: "frameHeight",
|
|
41088
41261
|
type: "INTEGER"
|
|
41262
|
+
},
|
|
41263
|
+
{
|
|
41264
|
+
name: "closedReason",
|
|
41265
|
+
type: "TEXT"
|
|
41089
41266
|
}
|
|
41090
41267
|
];
|
|
41091
41268
|
var TRACKS_INDEXES = [{
|
|
@@ -41145,7 +41322,8 @@ function cloneTrack(t) {
|
|
|
41145
41322
|
} : {},
|
|
41146
41323
|
...t.debug !== void 0 ? { debug: t.debug } : {},
|
|
41147
41324
|
...t.hasFace !== void 0 ? { hasFace: t.hasFace } : {},
|
|
41148
|
-
...t.hasRider !== void 0 ? { hasRider: t.hasRider } : {}
|
|
41325
|
+
...t.hasRider !== void 0 ? { hasRider: t.hasRider } : {},
|
|
41326
|
+
...t.closedReason !== void 0 ? { closedReason: t.closedReason } : {}
|
|
41149
41327
|
};
|
|
41150
41328
|
}
|
|
41151
41329
|
var TrackStore = class {
|
|
@@ -41714,13 +41892,22 @@ var TrackStore = class {
|
|
|
41714
41892
|
* nothing has been written under that id yet. It is never correct for a track
|
|
41715
41893
|
* that ran.
|
|
41716
41894
|
*
|
|
41895
|
+
* **The row SAYS why it was closed early** (`reason` → the `closedReason`
|
|
41896
|
+
* column). Persisting a promoted track put its footprint back under the
|
|
41897
|
+
* retention sweep, and it also put the parked car back in front of every
|
|
41898
|
+
* consumer that reads the window's tracks: the operator's nightly digest went
|
|
41899
|
+
* from 1-2 tiles to 10, most of them the same stationary car. The marker is
|
|
41900
|
+
* written HERE, at the one place that knows, so a consumer can ask for
|
|
41901
|
+
* passages exactly instead of guessing at movement from a stored trajectory.
|
|
41902
|
+
*
|
|
41717
41903
|
* Returns whether an active entry was found. THROWS if the persist fails: the
|
|
41718
41904
|
* caller must log it, because a swallowed failure here IS the leak.
|
|
41719
41905
|
*/
|
|
41720
|
-
async closeActive(trackId) {
|
|
41906
|
+
async closeActive(trackId, reason) {
|
|
41721
41907
|
const t = this.active.get(trackId);
|
|
41722
41908
|
if (t === void 0) return false;
|
|
41723
41909
|
t.active = false;
|
|
41910
|
+
t.closedReason = reason;
|
|
41724
41911
|
const record = cloneTrack(t);
|
|
41725
41912
|
await this.persistCompleted(record);
|
|
41726
41913
|
this.active.delete(trackId);
|
|
@@ -42302,6 +42489,7 @@ var TrackStore = class {
|
|
|
42302
42489
|
...t.debug !== void 0 ? { debug: t.debug } : {},
|
|
42303
42490
|
...t.hasFace !== void 0 ? { hasFace: t.hasFace } : {},
|
|
42304
42491
|
...t.hasRider !== void 0 ? { hasRider: t.hasRider } : {},
|
|
42492
|
+
...t.closedReason !== void 0 ? { closedReason: t.closedReason } : {},
|
|
42305
42493
|
...envelope !== null && dims !== void 0 ? {
|
|
42306
42494
|
envMinX: envelope.minX,
|
|
42307
42495
|
envMinY: envelope.minY,
|
|
@@ -42339,6 +42527,7 @@ var TrackStore = class {
|
|
|
42339
42527
|
const hasFace = data["hasFace"];
|
|
42340
42528
|
/** Same read as `hasFace` — NULL / missing stays ABSENT, never `false`. */
|
|
42341
42529
|
const hasRider = data["hasRider"];
|
|
42530
|
+
const closedReason = parseCloseReason(data["closedReason"]);
|
|
42342
42531
|
const envMinX = data["envMinX"];
|
|
42343
42532
|
const envMinY = data["envMinY"];
|
|
42344
42533
|
const envMaxX = data["envMaxX"];
|
|
@@ -42376,6 +42565,7 @@ var TrackStore = class {
|
|
|
42376
42565
|
...typeof debug === "boolean" ? { debug } : {},
|
|
42377
42566
|
...typeof hasFace === "boolean" ? { hasFace } : {},
|
|
42378
42567
|
...typeof hasRider === "boolean" ? { hasRider } : {},
|
|
42568
|
+
...closedReason !== void 0 ? { closedReason } : {},
|
|
42379
42569
|
...envelope !== null ? { envelope } : {}
|
|
42380
42570
|
};
|
|
42381
42571
|
}
|
|
@@ -49651,11 +49841,22 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
49651
49841
|
async onInitialize() {
|
|
49652
49842
|
const api = this.ctx.api;
|
|
49653
49843
|
if (!api) throw new Error("pipeline-analytics requires ctx.api (device-manager + settings-store)");
|
|
49654
|
-
|
|
49655
|
-
|
|
49844
|
+
const bootT0 = Date.now();
|
|
49845
|
+
const step = async (name, fn) => {
|
|
49846
|
+
const t0 = Date.now();
|
|
49847
|
+
const out = await fn();
|
|
49848
|
+
this.ctx.logger.info("pipeline-analytics boot step", { meta: {
|
|
49849
|
+
step: name,
|
|
49850
|
+
ms: Date.now() - t0,
|
|
49851
|
+
sinceBootMs: Date.now() - bootT0
|
|
49852
|
+
} });
|
|
49853
|
+
return out;
|
|
49854
|
+
};
|
|
49855
|
+
await step("declareCollections", () => this.declareCollections(api));
|
|
49856
|
+
await step("declareAlarmPanel", () => this.declareAlarmPanel(api));
|
|
49656
49857
|
const logger = this.ctx.logger;
|
|
49657
|
-
const storage = await this.resolveMediaStorage(logger);
|
|
49658
|
-
const stores = await this.buildStores(api, logger, storage);
|
|
49858
|
+
const storage = await step("resolveMediaStorage", () => this.resolveMediaStorage(logger));
|
|
49859
|
+
const stores = await step("buildStores", () => this.buildStores(api, logger, storage));
|
|
49659
49860
|
const rawNodeId = this.ctx.kernel.localNodeId ?? this.ctx.id;
|
|
49660
49861
|
const ownNodeId = rawNodeId.includes("/") ? rawNodeId.split("/")[0] : rawNodeId;
|
|
49661
49862
|
this.eventsOpsLog = new OpsLogStore({
|
|
@@ -49664,7 +49865,7 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
49664
49865
|
nodeId: ownNodeId
|
|
49665
49866
|
});
|
|
49666
49867
|
{
|
|
49667
|
-
const designated = await this.postProcessingNodeState.get();
|
|
49868
|
+
const designated = await step("postProcessingNodeState", () => this.postProcessingNodeState.get());
|
|
49668
49869
|
this.isPostProcessingNode = ownNodeId === designated;
|
|
49669
49870
|
if (!this.isPostProcessingNode) logger.info("pipeline-analytics INERT on this node — post-processing assigned elsewhere", { meta: {
|
|
49670
49871
|
ownNodeId,
|
|
@@ -49688,8 +49889,8 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
49688
49889
|
this.buildRecognizers(api, logger, stores, transport);
|
|
49689
49890
|
this.buildDetailDispatcher(api, logger, transport);
|
|
49690
49891
|
const capProviders = this.buildAnalyticsProviders(api, logger);
|
|
49691
|
-
await this.buildNotificationCenter(api, logger, stores);
|
|
49692
|
-
await this.serveEventMediaDataPlane();
|
|
49892
|
+
await step("buildNotificationCenter", () => this.buildNotificationCenter(api, logger, stores));
|
|
49893
|
+
await step("serveEventMediaDataPlane", () => this.serveEventMediaDataPlane());
|
|
49693
49894
|
this.subscriptionUnsubs = wireSubscriptions({
|
|
49694
49895
|
eventBus: this.ctx.eventBus,
|
|
49695
49896
|
isPostProcessingNode: this.isPostProcessingNode,
|
|
@@ -49705,11 +49906,11 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
49705
49906
|
onClusterTopology: (nodes) => this.nodeLiveness.applySnapshot(nodes, Date.now()),
|
|
49706
49907
|
onSystemEvent: (event) => this.notificationCenter?.onSystemEvent(event)
|
|
49707
49908
|
});
|
|
49708
|
-
if (this.isPostProcessingNode) await this.startEmbeddingDispatcher(logger, transport);
|
|
49709
|
-
await this.buildSceneMonitor(api, logger);
|
|
49909
|
+
if (this.isPostProcessingNode) await step("startEmbeddingDispatcher", () => this.startEmbeddingDispatcher(logger, transport));
|
|
49910
|
+
await step("buildSceneMonitor", () => this.buildSceneMonitor(api, logger));
|
|
49710
49911
|
this.startSweepTimers();
|
|
49711
49912
|
this.ctx.logger.info("pipeline-analytics subscribers installed");
|
|
49712
|
-
const providers = this.buildProviderRegistrations(api, stores, capProviders);
|
|
49913
|
+
const providers = await step("buildProviderRegistrations", () => this.buildProviderRegistrations(api, stores, capProviders));
|
|
49713
49914
|
const isHub = ownNodeId === "hub";
|
|
49714
49915
|
const ncHandlers = isHub ? this.buildNcActionHandlers(api) : void 0;
|
|
49715
49916
|
return {
|
|
@@ -49884,26 +50085,30 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
49884
50085
|
}
|
|
49885
50086
|
async declareCollections(api) {
|
|
49886
50087
|
this.settingsStore = api.settingsStore;
|
|
49887
|
-
await
|
|
49888
|
-
|
|
49889
|
-
|
|
49890
|
-
|
|
49891
|
-
|
|
49892
|
-
|
|
49893
|
-
|
|
49894
|
-
|
|
49895
|
-
|
|
49896
|
-
|
|
49897
|
-
|
|
49898
|
-
|
|
49899
|
-
|
|
49900
|
-
|
|
49901
|
-
|
|
49902
|
-
|
|
50088
|
+
await Promise.all([
|
|
50089
|
+
TrackStore.declare(api.settingsStore),
|
|
50090
|
+
MediaStore.declare(api.settingsStore),
|
|
50091
|
+
EventStore.declare(api.settingsStore),
|
|
50092
|
+
SensorEventStore.declare(api.settingsStore),
|
|
50093
|
+
IdentityStore.declare(api.settingsStore),
|
|
50094
|
+
FaceStore.declare(api.settingsStore),
|
|
50095
|
+
PlateStore.declare(api.settingsStore),
|
|
50096
|
+
VehicleStore.declare(api.settingsStore),
|
|
50097
|
+
StationaryObjectRegistry.declare(api.settingsStore),
|
|
50098
|
+
RetrainFrameStore.declare(api.settingsStore),
|
|
50099
|
+
RetrainAnnotationStore.declare(api.settingsStore),
|
|
50100
|
+
OpsLogStore.declare(api.settingsStore),
|
|
50101
|
+
AnalyticsLts.declare(api.settingsStore),
|
|
50102
|
+
SceneStore.declare(api.settingsStore),
|
|
50103
|
+
NotificationCenter.declare(api.settingsStore)
|
|
50104
|
+
]);
|
|
50105
|
+
runLabelTierMigration({
|
|
49903
50106
|
store: api.settingsStore,
|
|
49904
50107
|
logger: this.ctx.logger,
|
|
49905
50108
|
now: () => Date.now()
|
|
49906
|
-
}, [TRACKS_COLLECTION, OBJECT_EVENTS_COLLECTION])
|
|
50109
|
+
}, [TRACKS_COLLECTION, OBJECT_EVENTS_COLLECTION]).catch((err) => {
|
|
50110
|
+
this.ctx.logger.warn("label tier migration failed — will retry next boot", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
50111
|
+
});
|
|
49907
50112
|
}
|
|
49908
50113
|
/** Event-media storage. By default it uses `ctx.kernel.storage`, rooted at
|
|
49909
50114
|
* the node data dir (appData) → heavy thumbnail/track-frame churn hammers
|
|
@@ -50563,7 +50768,8 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
50563
50768
|
lastSeen: t.lastSeen,
|
|
50564
50769
|
...t.importance !== void 0 ? { importance: t.importance } : {},
|
|
50565
50770
|
zones: [...t.zonesVisited],
|
|
50566
|
-
...t.classes !== void 0 ? { classes: [...t.classes] } : {}
|
|
50771
|
+
...t.classes !== void 0 ? { classes: [...t.classes] } : {},
|
|
50772
|
+
...t.closedReason === "stationary-promotion" ? { stationary: true } : {}
|
|
50567
50773
|
}));
|
|
50568
50774
|
},
|
|
50569
50775
|
listMediaInfo: async (trackId) => {
|
|
@@ -51667,10 +51873,12 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
51667
51873
|
this.trackStore?.markRiderFolded(fold.trackId);
|
|
51668
51874
|
}
|
|
51669
51875
|
if (source === "pipeline") this.stationaryRegistry?.noteFrame(deviceId, result.timestamp);
|
|
51670
|
-
if (this.stationaryRegistry && (result.stationaryConfirmed.length > 0 || result.stationaryWoken.length > 0)) this.stationaryRegistry.applyFrameOutcome({
|
|
51876
|
+
if (this.stationaryRegistry && (result.stationaryConfirmed.length > 0 || result.stationaryWoken.length > 0 || result.stationaryArmed.length > 0 || result.stationaryDisarmed.length > 0)) this.stationaryRegistry.applyFrameOutcome({
|
|
51671
51877
|
deviceId,
|
|
51672
51878
|
confirmed: result.stationaryConfirmed,
|
|
51673
51879
|
wokenEntryIds: result.stationaryWoken,
|
|
51880
|
+
armedEntryIds: result.stationaryArmed,
|
|
51881
|
+
disarmedEntryIds: result.stationaryDisarmed,
|
|
51674
51882
|
timestamp: result.timestamp
|
|
51675
51883
|
});
|
|
51676
51884
|
const stationaryViews = this.stationaryRegistry?.listViews(deviceId) ?? [];
|
|
@@ -53727,7 +53935,7 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
53727
53935
|
};
|
|
53728
53936
|
if (plausible) this.stationaryRegistry?.promote(entry);
|
|
53729
53937
|
processor.dropTrack(track.trackId);
|
|
53730
|
-
this.trackStore?.closeActive(track.trackId).catch((err) => {
|
|
53938
|
+
this.trackStore?.closeActive(track.trackId, "stationary-promotion").catch((err) => {
|
|
53731
53939
|
this.ctx.logger.warn("stationary promotion: closing the source track failed — its media, events and vector are now unowned", {
|
|
53732
53940
|
tags: { deviceId },
|
|
53733
53941
|
meta: {
|
|
@@ -53830,7 +54038,9 @@ var PipelineAnalyticsAddon = class extends BaseAddon {
|
|
|
53830
54038
|
if (!s.enabled) return {
|
|
53831
54039
|
suppressedIndices: /* @__PURE__ */ new Set(),
|
|
53832
54040
|
confirmed: [],
|
|
53833
|
-
wokenEntryIds: []
|
|
54041
|
+
wokenEntryIds: [],
|
|
54042
|
+
armedEntryIds: [],
|
|
54043
|
+
disarmedEntryIds: []
|
|
53834
54044
|
};
|
|
53835
54045
|
const matchConfig = {
|
|
53836
54046
|
suppressIou: s.suppressIou,
|
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DHm8hb9G.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-post-analysis",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.80",
|
|
4
4
|
"description": "Post-Analysis bundle — enrichment, embedding-encoder, pipeline-analytics. Multi-entry npm package shipping addons that consume pipeline output.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|