@camstack/addon-post-analysis 1.2.289 → 1.2.291
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/{clip-model-registry-JFtcAZEB.js → clip-model-registry-CTY5co6P.js} +472 -27
- package/dist/{clip-model-registry-g3-Yz08Y.mjs → clip-model-registry-Cudz--Ql.mjs} +472 -27
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +2 -2
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-D5OpYfsh.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CBHxwCSj.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-2OwTV_D2.mjs +26 -0
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DAAKQ3sC.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-BsQiXbDx.mjs → hostInit-DSKT2dE4.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +322 -59
- package/dist/pipeline-analytics/index.mjs +322 -59
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CfU5NAwo.mjs +0 -26
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-r4OU_ahc.mjs +0 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as NcRuleSchema, $n as EventCategory, $t as isSourceCap, A as LabelAttributionSchema, An as canonicalHash, At as audioMetricsCapability, B as NC_DEFAULT_SNOOZE_MINUTES, Bt as embeddingRefusalOf, C as EMBEDDING_REQUIREMENTS_FAILED, Cn as systemEventFilterApplies, Ct as TimelapseRuleInputSchema, D as FIRST_LEVEL_MACRO_CLASSES, Dn as vectorDimFromBase64, Dt as addonWidgetsSourceCapability, E as EVENT_OWNER_TYPES, En as templateVarsFor, Et as TrackSourceSchema, F as MOTION_CLOSE_AFTER_MS, Fn as customAction, Ft as deriveRecordingMode, G as NC_TAXONOMY, Gn as discriminatedUnion, Gt as evictionPolicyOfLocation, Hn as _enum, I as MediaFileKindEnum, In as defineCustomActions, It as describeSystemEventDeliveryProblem, J as NcAlarmSettingsPatchSchema, Jn as object, Jt as isDetectionMacroClass, K as NC_TEMPLATE_VARS, Kn as literal, Kt as faceGalleryCapability, L as NC_ALARM_SYSTEM_EVENT_KINDS, Ln as hydrateSchema, Lt as describeSystemEventFamilyProblem, M as MAX_ARCHIVED_DEBUG_NOTES, Mn as CamProfileSchema, Mt as buildEventKindDescriptor, N as MAX_BIRTH_DECISION_RECORDS, Nn as DeviceType, Nt as consumableLowPercentOf, O as FULL_IMAGE_BBOX, On as zoneAnalyticsCapability, Ot as alarmPanelCapability, Pn as createEvent, Pt as cosineSimilarity$1, Q as NcRulePatchSchema, Qn as unknown, Qt as isScheduleActive, R as NC_CONDITION_CATALOG, Rn as isDeviceScopedCap, S as EMBEDDING_MODEL_FAILED, Sn as systemEventFamilyProblems, St as TIMELAPSE_DENSE_FLOOR_SEC, T as EVENT_KIND_BY_CAP, Tn as templateCarriesSummary, Tt as TimelapseRuleSchema, U as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, Un as array, Ut as encodeVectorBase64, V as NC_SENSOR_TRANSITION_KINDS, Vn as sleep$1, W as NC_TANK_SYSTEM_EVENT_KINDS, Wn as boolean, Wt as evaluateSensorEdge, X as NcConditionsSchema, Xn as record, Xt as isKnownTemplateVar, Y as NcConditionDescriptorSchema, Yn as partialRecord, Yt as isEventOwnerType, Z as NcRuleInputSchema, Zn as string, Zt as isMediaOwnerType, _n as sensorRaisedOf, a as CLIP_EMBEDDING_STEP_ID, an as notificationRulesCapability, at as NcSnoozeSuppressedSchema, bn as subKindsOf, bt as SCENE_DIVERGED, c as resolveClusterModelPin, cn as pipelineAnalyticsCapability, ct as NcTemplatePreviewInputSchema, d as ArchivedDebugNoteSchema, dn as readTimelapseGeneratedAt, dt as OpsLogEntrySchema, en as isSystemDelivery, et as NcRuleTargetSchema, f as BaseDevice, fn as resolveClipSearchMinScore, g as DEFAULT_EVENT_COLOR, gn as sceneMonitorCapability, gt as RetrainStatusSchema, h as CoverStateSchema, hn as ruleBelongsToAlarm$1, ht as RebuildObjectEmbeddingsRefusalSchema, in as mayWriteToLocation, it as NcSnoozeSchema, j as LockStateSchema, jn as BaseAddon, jt as audioModeOf, k as FailureCounters, kn as errMsg$1, kt as assertTimelapseCadences, l as AUDIO_MACRO_LABELS, ln as plateGalleryCapability, lt as NcTemplatePreviewSchema, m as COCO_TO_MACRO, mt as RECORDING_SOURCE_CAMSTACK_ADDON, nn as isVectorIndexDimConflict, nt as NcScheduleSchema, o as FACE_EMBEDDING_STEP_ID, on as occupancyScope, ot as NcSystemEventKindSchema, p as BirthDecisionRecordSchema, pn as resolveLocationMode, pt as RECORDING_EXPORT_MAX_READ_BYTES, q as NcAlarmConfigSchema, qn as number, qt as failureContributionCapability, rn as kebabToCamel, rt as NcSnoozeInputSchema, s as readClusterModelPinStrict, st as NcTaxonomySchema, t as BUILTIN_CLIP_MODELS, tn as isSystemEventSummaryRule, tt as NcRuleUpdateInputSchema, u as AlarmArmModeSchema, un as readDeviceStateFrom, ut as NcTemplateVarDescriptorSchema, vn as servedTemplateVars, vt as SCENE_DEFAULT_ANCHOR_THRESHOLD, w as EMBEDDING_REQUIREMENTS_UNAVAILABLE, wn as systemEventSummaryScheduleOf, wt as TimelapseRulePatchSchema, x as DeclaredDevices, xn as systemEventDeliveryProblems, xt as SceneMonitorSchema, y as DETECTION_MACRO_CLASSES, yn as storageOccupancyCapability, yt as SCENE_DEFAULT_UNCOVERED_POLICY, z as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, zn as nodePin } from "../clip-model-registry-
|
|
1
|
+
import { $ as NcRuleSchema, $n as EventCategory, $t as isSourceCap, A as LabelAttributionSchema, An as canonicalHash, At as audioMetricsCapability, B as NC_DEFAULT_SNOOZE_MINUTES, Bt as embeddingRefusalOf, C as EMBEDDING_REQUIREMENTS_FAILED, Cn as systemEventFilterApplies, Ct as TimelapseRuleInputSchema, D as FIRST_LEVEL_MACRO_CLASSES, Dn as vectorDimFromBase64, Dt as addonWidgetsSourceCapability, E as EVENT_OWNER_TYPES, En as templateVarsFor, Et as TrackSourceSchema, F as MOTION_CLOSE_AFTER_MS, Fn as customAction, Ft as deriveRecordingMode, G as NC_TAXONOMY, Gn as discriminatedUnion, Gt as evictionPolicyOfLocation, Hn as _enum, I as MediaFileKindEnum, In as defineCustomActions, It as describeSystemEventDeliveryProblem, J as NcAlarmSettingsPatchSchema, Jn as object, Jt as isDetectionMacroClass, K as NC_TEMPLATE_VARS, Kn as literal, Kt as faceGalleryCapability, L as NC_ALARM_SYSTEM_EVENT_KINDS, Ln as hydrateSchema, Lt as describeSystemEventFamilyProblem, M as MAX_ARCHIVED_DEBUG_NOTES, Mn as CamProfileSchema, Mt as buildEventKindDescriptor, N as MAX_BIRTH_DECISION_RECORDS, Nn as DeviceType, Nt as consumableLowPercentOf, O as FULL_IMAGE_BBOX, On as zoneAnalyticsCapability, Ot as alarmPanelCapability, Pn as createEvent, Pt as cosineSimilarity$1, Q as NcRulePatchSchema, Qn as unknown, Qt as isScheduleActive, R as NC_CONDITION_CATALOG, Rn as isDeviceScopedCap, S as EMBEDDING_MODEL_FAILED, Sn as systemEventFamilyProblems, St as TIMELAPSE_DENSE_FLOOR_SEC, T as EVENT_KIND_BY_CAP, Tn as templateCarriesSummary, Tt as TimelapseRuleSchema, U as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, Un as array, Ut as encodeVectorBase64, V as NC_SENSOR_TRANSITION_KINDS, Vn as sleep$1, W as NC_TANK_SYSTEM_EVENT_KINDS, Wn as boolean, Wt as evaluateSensorEdge, X as NcConditionsSchema, Xn as record, Xt as isKnownTemplateVar, Y as NcConditionDescriptorSchema, Yn as partialRecord, Yt as isEventOwnerType, Z as NcRuleInputSchema, Zn as string, Zt as isMediaOwnerType, _n as sensorRaisedOf, a as CLIP_EMBEDDING_STEP_ID, an as notificationRulesCapability, at as NcSnoozeSuppressedSchema, bn as subKindsOf, bt as SCENE_DIVERGED, c as resolveClusterModelPin, cn as pipelineAnalyticsCapability, ct as NcTemplatePreviewInputSchema, d as ArchivedDebugNoteSchema, dn as readTimelapseGeneratedAt, dt as OpsLogEntrySchema, en as isSystemDelivery, et as NcRuleTargetSchema, f as BaseDevice, fn as resolveClipSearchMinScore, g as DEFAULT_EVENT_COLOR, gn as sceneMonitorCapability, gt as RetrainStatusSchema, h as CoverStateSchema, hn as ruleBelongsToAlarm$1, ht as RebuildObjectEmbeddingsRefusalSchema, in as mayWriteToLocation, it as NcSnoozeSchema, j as LockStateSchema, jn as BaseAddon, jt as audioModeOf, k as FailureCounters, kn as errMsg$1, kt as assertTimelapseCadences, l as AUDIO_MACRO_LABELS, ln as plateGalleryCapability, lt as NcTemplatePreviewSchema, m as COCO_TO_MACRO, mt as RECORDING_SOURCE_CAMSTACK_ADDON, nn as isVectorIndexDimConflict, nt as NcScheduleSchema, o as FACE_EMBEDDING_STEP_ID, on as occupancyScope, ot as NcSystemEventKindSchema, p as BirthDecisionRecordSchema, pn as resolveLocationMode, pt as RECORDING_EXPORT_MAX_READ_BYTES, q as NcAlarmConfigSchema, qn as number, qt as failureContributionCapability, rn as kebabToCamel, rt as NcSnoozeInputSchema, s as readClusterModelPinStrict, st as NcTaxonomySchema, t as BUILTIN_CLIP_MODELS, tn as isSystemEventSummaryRule, tt as NcRuleUpdateInputSchema, u as AlarmArmModeSchema, un as readDeviceStateFrom, ut as NcTemplateVarDescriptorSchema, vn as servedTemplateVars, vt as SCENE_DEFAULT_ANCHOR_THRESHOLD, w as EMBEDDING_REQUIREMENTS_UNAVAILABLE, wn as systemEventSummaryScheduleOf, wt as TimelapseRulePatchSchema, x as DeclaredDevices, xn as systemEventDeliveryProblems, xt as SceneMonitorSchema, y as DETECTION_MACRO_CLASSES, yn as storageOccupancyCapability, yt as SCENE_DEFAULT_UNCOVERED_POLICY, z as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, zn as nodePin } from "../clip-model-registry-Cudz--Ql.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";
|
|
@@ -39654,7 +39654,12 @@ var RebuildInputSchema = object({
|
|
|
39654
39654
|
* Milliseconds between tracks; omit for the default, `0` to run flat out.
|
|
39655
39655
|
* A rebuild shares hub-main's only thread with every live request.
|
|
39656
39656
|
*/
|
|
39657
|
-
pacingMs: number().int().nonnegative().optional()
|
|
39657
|
+
pacingMs: number().int().nonnegative().optional(),
|
|
39658
|
+
/**
|
|
39659
|
+
* Re-embed ONLY tracks already in the pinned space — to redo vectors cut
|
|
39660
|
+
* from the wrong box (D664). Requires `maxTracks`.
|
|
39661
|
+
*/
|
|
39662
|
+
force: boolean().optional()
|
|
39658
39663
|
});
|
|
39659
39664
|
var RebuildStartedSchema = object({
|
|
39660
39665
|
started: boolean(),
|
|
@@ -39674,7 +39679,20 @@ var RebuildStatusSchema = object({
|
|
|
39674
39679
|
scanned: number(),
|
|
39675
39680
|
rebuilt: number(),
|
|
39676
39681
|
missingKeyFrame: number(),
|
|
39682
|
+
/** No object event at all — its own number since D664. */
|
|
39683
|
+
missingEvent: number(),
|
|
39677
39684
|
missingBbox: number(),
|
|
39685
|
+
/** Which rule placed each judged track's box (D664). */
|
|
39686
|
+
boxSource: object({
|
|
39687
|
+
subjectBox: number(),
|
|
39688
|
+
positions: number(),
|
|
39689
|
+
event: number(),
|
|
39690
|
+
refused: number()
|
|
39691
|
+
}),
|
|
39692
|
+
alreadyInSpace: number(),
|
|
39693
|
+
/** Whether the current / last pass was a `force` pass (D664). */
|
|
39694
|
+
force: boolean().nullable(),
|
|
39695
|
+
forcedInSpace: number(),
|
|
39678
39696
|
/** Refused by the executing node (unreadable key frame / bad box), not broken. */
|
|
39679
39697
|
notRunnable: number(),
|
|
39680
39698
|
/** The pass STOPPED: no node in the cluster could serve the pinned model. */
|
|
@@ -40949,7 +40967,7 @@ function toPixelBox(b) {
|
|
|
40949
40967
|
h: b.height
|
|
40950
40968
|
};
|
|
40951
40969
|
}
|
|
40952
|
-
function refused(reason, detail) {
|
|
40970
|
+
function refused$1(reason, detail) {
|
|
40953
40971
|
return {
|
|
40954
40972
|
kind: "refused",
|
|
40955
40973
|
reason,
|
|
@@ -40977,8 +40995,8 @@ function comparableFaces(input) {
|
|
|
40977
40995
|
/** Refuse before choosing when nothing in the photo can become the sample. */
|
|
40978
40996
|
function precondition(input) {
|
|
40979
40997
|
const enrollable = input.faces.filter((f) => f.enrollable && f.embedding !== void 0);
|
|
40980
|
-
if (enrollable.length === 0) return refused("no-enrollable-face", `${input.faces.length} face(s) found, none enrollable (${input.faces.map((f) => f.refusedReason ?? "unknown").join(", ")})`);
|
|
40981
|
-
if (!enrollable.some((f) => isEnrollableIn(f, input.modelId))) return refused("model-mismatch", `faces were embedded by ${[...new Set(enrollable.map((f) => f.modelId))].join(", ")}, the old sample by ${input.modelId} — re-embed the gallery first`);
|
|
40998
|
+
if (enrollable.length === 0) return refused$1("no-enrollable-face", `${input.faces.length} face(s) found, none enrollable (${input.faces.map((f) => f.refusedReason ?? "unknown").join(", ")})`);
|
|
40999
|
+
if (!enrollable.some((f) => isEnrollableIn(f, input.modelId))) return refused$1("model-mismatch", `faces were embedded by ${[...new Set(enrollable.map((f) => f.modelId))].join(", ")}, the old sample by ${input.modelId} — re-embed the gallery first`);
|
|
40982
41000
|
return null;
|
|
40983
41001
|
}
|
|
40984
41002
|
function chooseByIou(input, oldBox, scored) {
|
|
@@ -40987,13 +41005,13 @@ function chooseByIou(input, oldBox, scored) {
|
|
|
40987
41005
|
face,
|
|
40988
41006
|
iou: iou$3(box, toPixelBox(face.bbox))
|
|
40989
41007
|
})).filter((c) => c.iou >= PHOTO_REENROL_MIN_IOU);
|
|
40990
|
-
if (overlapping.length === 0) return refused("no-iou-match", `no face overlaps the old box at IoU ≥ ${PHOTO_REENROL_MIN_IOU}`);
|
|
40991
|
-
if (overlapping.length > 1) return refused("ambiguous", `${overlapping.length} faces overlap the old box (IoU ${overlapping.map((c) => c.iou.toFixed(2)).join(", ")})`);
|
|
41008
|
+
if (overlapping.length === 0) return refused$1("no-iou-match", `no face overlaps the old box at IoU ≥ ${PHOTO_REENROL_MIN_IOU}`);
|
|
41009
|
+
if (overlapping.length > 1) return refused$1("ambiguous", `${overlapping.length} faces overlap the old box (IoU ${overlapping.map((c) => c.iou.toFixed(2)).join(", ")})`);
|
|
40992
41010
|
const [only] = overlapping;
|
|
40993
|
-
if (only === void 0) return refused("no-iou-match", "no overlapping face");
|
|
40994
|
-
if (!isEnrollableIn(only.face, input.modelId)) return refused("no-enrollable-face", `the face on the old box is not enrollable (${only.face.refusedReason ?? `model ${only.face.modelId ?? "none"}`})`);
|
|
41011
|
+
if (only === void 0) return refused$1("no-iou-match", "no overlapping face");
|
|
41012
|
+
if (!isEnrollableIn(only.face, input.modelId)) return refused$1("no-enrollable-face", `the face on the old box is not enrollable (${only.face.refusedReason ?? `model ${only.face.modelId ?? "none"}`})`);
|
|
40995
41013
|
const cosine = scored.find((s) => s.face === only.face)?.cosine;
|
|
40996
|
-
if (cosine === void 0 || cosine < .5) return refused("below-floor", `the overlapping face scores cosine ${cosine?.toFixed(3) ?? "n/a"} < ${PHOTO_REENROL_COSINE_FLOOR}`);
|
|
41014
|
+
if (cosine === void 0 || cosine < .5) return refused$1("below-floor", `the overlapping face scores cosine ${cosine?.toFixed(3) ?? "n/a"} < ${PHOTO_REENROL_COSINE_FLOOR}`);
|
|
40997
41015
|
return {
|
|
40998
41016
|
kind: "chosen",
|
|
40999
41017
|
face: only.face,
|
|
@@ -41004,10 +41022,10 @@ function chooseByIou(input, oldBox, scored) {
|
|
|
41004
41022
|
}
|
|
41005
41023
|
function chooseByCosine(input, scored) {
|
|
41006
41024
|
const [best, runnerUp] = [...scored].toSorted((a, b) => b.cosine - a.cosine);
|
|
41007
|
-
if (best === void 0) return refused("model-mismatch", "no face has a comparable vector");
|
|
41008
|
-
if (best.cosine < .5) return refused("below-floor", `best cosine ${best.cosine.toFixed(3)} < ${PHOTO_REENROL_COSINE_FLOOR}`);
|
|
41009
|
-
if (runnerUp !== void 0 && runnerUp.cosine >= .5 && best.cosine - runnerUp.cosine < .1) return refused("ambiguous", `two faces clear the floor within ${PHOTO_REENROL_AMBIGUITY_MARGIN}: ${best.cosine.toFixed(3)} vs ${runnerUp.cosine.toFixed(3)}`);
|
|
41010
|
-
if (!isEnrollableIn(best.face, input.modelId)) return refused("ambiguous", `the closest face (cosine ${best.cosine.toFixed(3)}) is not enrollable (${best.face.refusedReason ?? "unknown"}) — the enrollable ones may be someone else`);
|
|
41025
|
+
if (best === void 0) return refused$1("model-mismatch", "no face has a comparable vector");
|
|
41026
|
+
if (best.cosine < .5) return refused$1("below-floor", `best cosine ${best.cosine.toFixed(3)} < ${PHOTO_REENROL_COSINE_FLOOR}`);
|
|
41027
|
+
if (runnerUp !== void 0 && runnerUp.cosine >= .5 && best.cosine - runnerUp.cosine < .1) return refused$1("ambiguous", `two faces clear the floor within ${PHOTO_REENROL_AMBIGUITY_MARGIN}: ${best.cosine.toFixed(3)} vs ${runnerUp.cosine.toFixed(3)}`);
|
|
41028
|
+
if (!isEnrollableIn(best.face, input.modelId)) return refused$1("ambiguous", `the closest face (cosine ${best.cosine.toFixed(3)}) is not enrollable (${best.face.refusedReason ?? "unknown"}) — the enrollable ones may be someone else`);
|
|
41011
41029
|
return {
|
|
41012
41030
|
kind: "chosen",
|
|
41013
41031
|
face: best.face,
|
|
@@ -53721,11 +53739,10 @@ var EventStore = class {
|
|
|
53721
53739
|
let entryId;
|
|
53722
53740
|
for (const row of rows) {
|
|
53723
53741
|
const bbox = row.data["bbox"];
|
|
53724
|
-
if (bbox
|
|
53725
|
-
|
|
53726
|
-
|
|
53727
|
-
|
|
53728
|
-
}
|
|
53742
|
+
if (bbox === null || typeof bbox !== "object") continue;
|
|
53743
|
+
const bw = "w" in bbox && typeof bbox.w === "number" ? bbox.w : 0;
|
|
53744
|
+
const bh = "h" in bbox && typeof bbox.h === "number" ? bbox.h : 0;
|
|
53745
|
+
if (bw <= 0 || bh <= 0) continue;
|
|
53729
53746
|
const conf = typeof row.data["confidence"] === "number" ? row.data["confidence"] : 0;
|
|
53730
53747
|
if (conf > bestConf) {
|
|
53731
53748
|
bestConf = conf;
|
|
@@ -62377,6 +62394,26 @@ var EmbeddingDispatcher = class {
|
|
|
62377
62394
|
return this.pendingCrops.size;
|
|
62378
62395
|
}
|
|
62379
62396
|
};
|
|
62397
|
+
//#endregion
|
|
62398
|
+
//#region src/pipeline-analytics/embedding-rebuild.ts
|
|
62399
|
+
/**
|
|
62400
|
+
* Track sources a rebuild never lists (D664). An audio track and a synthetic
|
|
62401
|
+
* sensor track have no object event and no subject to embed — on the live hub
|
|
62402
|
+
* 6,726 + 180 of 42,254 tracks — and walking them only inflated the skip
|
|
62403
|
+
* counters an operator reads to judge media coverage.
|
|
62404
|
+
*/
|
|
62405
|
+
var REBUILD_EXCLUDED_SOURCES = ["audio", "sensor"];
|
|
62406
|
+
/**
|
|
62407
|
+
* One page of the rebuild listing as a `queryRecentIds` query. Pure, so the
|
|
62408
|
+
* exclusion is assertable: dropping it would look identical in every result
|
|
62409
|
+
* except the skip counters.
|
|
62410
|
+
*/
|
|
62411
|
+
function rebuildTrackPageQuery(window) {
|
|
62412
|
+
return {
|
|
62413
|
+
...window,
|
|
62414
|
+
excludeSources: REBUILD_EXCLUDED_SOURCES
|
|
62415
|
+
};
|
|
62416
|
+
}
|
|
62380
62417
|
/**
|
|
62381
62418
|
* Re-embed every listed track from its key frame.
|
|
62382
62419
|
*
|
|
@@ -62392,6 +62429,14 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62392
62429
|
let recoveredKeyFrame = 0;
|
|
62393
62430
|
let missingEvent = 0;
|
|
62394
62431
|
let missingBbox = 0;
|
|
62432
|
+
let boxSubject = 0;
|
|
62433
|
+
let boxPositions = 0;
|
|
62434
|
+
let boxEvent = 0;
|
|
62435
|
+
let boxRefused = 0;
|
|
62436
|
+
let forcedInSpace = 0;
|
|
62437
|
+
let skippedOutOfSpace = 0;
|
|
62438
|
+
const refusalsByDevice = /* @__PURE__ */ new Map();
|
|
62439
|
+
const force = options.force === true;
|
|
62395
62440
|
let alreadyInSpace = 0;
|
|
62396
62441
|
let notRunnable = 0;
|
|
62397
62442
|
let noCapableNode = 0;
|
|
@@ -62402,6 +62447,12 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62402
62447
|
let budgetExhausted = false;
|
|
62403
62448
|
/** Set when the cluster ran out of nodes — the pass stops, `complete` is false. */
|
|
62404
62449
|
let abandoned = null;
|
|
62450
|
+
const boxSourceCounts = () => ({
|
|
62451
|
+
subjectBox: boxSubject,
|
|
62452
|
+
positions: boxPositions,
|
|
62453
|
+
event: boxEvent,
|
|
62454
|
+
refused: boxRefused
|
|
62455
|
+
});
|
|
62405
62456
|
while (scanned < maxTracks && abandoned === null) {
|
|
62406
62457
|
const page = await deps.listTrackIdPage(cursor);
|
|
62407
62458
|
if (page.trackIds.length === 0) {
|
|
@@ -62409,9 +62460,14 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62409
62460
|
break;
|
|
62410
62461
|
}
|
|
62411
62462
|
let pageIds = page.trackIds;
|
|
62463
|
+
let forcedPage = false;
|
|
62412
62464
|
if (deps.filterOutOfSpace) {
|
|
62413
62465
|
const split = await deps.filterOutOfSpace(page.trackIds);
|
|
62414
|
-
if (split !== null) {
|
|
62466
|
+
if (split !== null && force) {
|
|
62467
|
+
skippedOutOfSpace += split.outOfSpace.length;
|
|
62468
|
+
pageIds = split.inSpace;
|
|
62469
|
+
forcedPage = true;
|
|
62470
|
+
} else if (split !== null) {
|
|
62415
62471
|
alreadyInSpace += split.alreadyInSpace;
|
|
62416
62472
|
pageIds = split.outOfSpace;
|
|
62417
62473
|
}
|
|
@@ -62427,6 +62483,7 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62427
62483
|
const room = maxTracks - scanned;
|
|
62428
62484
|
const batch = pageIds.slice(0, Number.isFinite(room) ? room : void 0);
|
|
62429
62485
|
if (batch.length < pageIds.length) budgetExhausted = true;
|
|
62486
|
+
if (forcedPage) forcedInSpace += batch.length;
|
|
62430
62487
|
for (const trackId of batch) {
|
|
62431
62488
|
if (!deps.canDispatch()) {
|
|
62432
62489
|
abandoned = "no node left in the rotation can serve the pinned model — stopped before loading any further media";
|
|
@@ -62445,6 +62502,25 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62445
62502
|
missingEvent += 1;
|
|
62446
62503
|
return;
|
|
62447
62504
|
}
|
|
62505
|
+
if (source.bbox === null || source.bbox.w <= 0 || source.bbox.h <= 0) {
|
|
62506
|
+
missingBbox += 1;
|
|
62507
|
+
boxRefused += 1;
|
|
62508
|
+
const reason = source.boxSource.kind === "refused" ? source.boxSource.reason : "degenerate-box";
|
|
62509
|
+
const n = (refusalsByDevice.get(source.deviceId) ?? 0) + 1;
|
|
62510
|
+
refusalsByDevice.set(source.deviceId, n);
|
|
62511
|
+
if (n === 1 || n % 100 === 0) deps.logger.warn("embedding rebuild: no box measured on the key frame — track refused (D303)", {
|
|
62512
|
+
tags: { deviceId: source.deviceId },
|
|
62513
|
+
meta: {
|
|
62514
|
+
trackId,
|
|
62515
|
+
reason,
|
|
62516
|
+
refusedOnThisCamera: n
|
|
62517
|
+
}
|
|
62518
|
+
});
|
|
62519
|
+
return;
|
|
62520
|
+
}
|
|
62521
|
+
if (source.boxSource.kind === "subjectBox") boxSubject += 1;
|
|
62522
|
+
else if (source.boxSource.kind === "positions") boxPositions += 1;
|
|
62523
|
+
else boxEvent += 1;
|
|
62448
62524
|
let keyFrame = source.keyFrame;
|
|
62449
62525
|
let recovered = false;
|
|
62450
62526
|
if (keyFrame === null && deps.recoverKeyFrame) {
|
|
@@ -62456,10 +62532,6 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62456
62532
|
return;
|
|
62457
62533
|
}
|
|
62458
62534
|
if (recovered) recoveredKeyFrame += 1;
|
|
62459
|
-
if (source.bbox === null || source.bbox.w <= 0 || source.bbox.h <= 0) {
|
|
62460
|
-
missingBbox += 1;
|
|
62461
|
-
return;
|
|
62462
|
-
}
|
|
62463
62535
|
const outcome = await deps.embed(recovered ? {
|
|
62464
62536
|
...source,
|
|
62465
62537
|
keyFrame
|
|
@@ -62527,6 +62599,9 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62527
62599
|
recoveredKeyFrame,
|
|
62528
62600
|
missingEvent,
|
|
62529
62601
|
missingBbox,
|
|
62602
|
+
boxSource: boxSourceCounts(),
|
|
62603
|
+
forcedInSpace,
|
|
62604
|
+
skippedOutOfSpace,
|
|
62530
62605
|
alreadyInSpace,
|
|
62531
62606
|
notRunnable,
|
|
62532
62607
|
noCapableNode,
|
|
@@ -62550,6 +62625,10 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62550
62625
|
recoveredKeyFrame,
|
|
62551
62626
|
missingEvent,
|
|
62552
62627
|
missingBbox,
|
|
62628
|
+
boxSource: boxSourceCounts(),
|
|
62629
|
+
force,
|
|
62630
|
+
forcedInSpace,
|
|
62631
|
+
skippedOutOfSpace,
|
|
62553
62632
|
alreadyInSpace,
|
|
62554
62633
|
notRunnable,
|
|
62555
62634
|
noCapableNode,
|
|
@@ -62564,6 +62643,9 @@ async function rebuildObjectEmbeddings(deps, options = {}) {
|
|
|
62564
62643
|
recoveredKeyFrame,
|
|
62565
62644
|
missingEvent,
|
|
62566
62645
|
missingBbox,
|
|
62646
|
+
boxSource: boxSourceCounts(),
|
|
62647
|
+
forcedInSpace,
|
|
62648
|
+
skippedOutOfSpace,
|
|
62567
62649
|
alreadyInSpace,
|
|
62568
62650
|
notRunnable,
|
|
62569
62651
|
noCapableNode,
|
|
@@ -62920,8 +63002,6 @@ var FaceSettingsSchema = object({
|
|
|
62920
63002
|
* (2026-07-23), then →0.12 (2026-08-18) alongside the threshold retune —
|
|
62921
63003
|
* same story and the same recalibration plan as {@link similarityThreshold}. */
|
|
62922
63004
|
margin: number().min(0).max(1).default(.12),
|
|
62923
|
-
/** Minimum face-detection confidence for a face to be considered. */
|
|
62924
|
-
minFaceConfidence: number().min(0).max(1).default(.5),
|
|
62925
63005
|
/**
|
|
62926
63006
|
* Minimum face bbox size (px, shorter side, NATIVE scale when the runner
|
|
62927
63007
|
* measured it, else detection-frame space) for a face to be DETECTED and
|
|
@@ -63003,7 +63083,6 @@ function resolveFaceSettings(raw) {
|
|
|
63003
63083
|
enabled: pick("enabled"),
|
|
63004
63084
|
similarityThreshold: pick("similarityThreshold"),
|
|
63005
63085
|
margin: pick("margin"),
|
|
63006
|
-
minFaceConfidence: pick("minFaceConfidence"),
|
|
63007
63086
|
minFacePx: pick("minFacePx"),
|
|
63008
63087
|
recognitionMinFacePx: pick("recognitionMinFacePx"),
|
|
63009
63088
|
minIdentitySamples: pick("minIdentitySamples"),
|
|
@@ -63076,6 +63155,17 @@ function deriveSuggestedBufferCap(bufferMaxPerDevice) {
|
|
|
63076
63155
|
* it from a store.
|
|
63077
63156
|
*/
|
|
63078
63157
|
var STORED_SUGGESTION_MIN_COSINE_KEY = "suggestionMinCosine";
|
|
63158
|
+
/** The settings key that held the retired recognizer face-confidence bar (D662). */
|
|
63159
|
+
var STORED_MIN_FACE_CONFIDENCE_KEY = "minFaceConfidence";
|
|
63160
|
+
/** Plan the removal of ONE retired key from a settings blob; `null` = absent. */
|
|
63161
|
+
function planRetiredKeyPurge(raw, key) {
|
|
63162
|
+
const was = raw[key];
|
|
63163
|
+
if (was === void 0) return null;
|
|
63164
|
+
return {
|
|
63165
|
+
was,
|
|
63166
|
+
patch: { [key]: void 0 }
|
|
63167
|
+
};
|
|
63168
|
+
}
|
|
63079
63169
|
/**
|
|
63080
63170
|
* Plan the removal of a persisted suggestion floor from one settings blob.
|
|
63081
63171
|
*
|
|
@@ -63090,12 +63180,15 @@ var STORED_SUGGESTION_MIN_COSINE_KEY = "suggestionMinCosine";
|
|
|
63090
63180
|
* serialisation the blob round-trips through.
|
|
63091
63181
|
*/
|
|
63092
63182
|
function planStoredSuggestionPurge(raw) {
|
|
63093
|
-
|
|
63094
|
-
|
|
63095
|
-
|
|
63096
|
-
|
|
63097
|
-
|
|
63098
|
-
|
|
63183
|
+
return planRetiredKeyPurge(raw, STORED_SUGGESTION_MIN_COSINE_KEY);
|
|
63184
|
+
}
|
|
63185
|
+
/**
|
|
63186
|
+
* Plan the removal of a persisted `minFaceConfidence` (D662). Same contract as
|
|
63187
|
+
* {@link planStoredSuggestionPurge}: absence of the key is the marker, and the
|
|
63188
|
+
* patch unsets with `undefined`.
|
|
63189
|
+
*/
|
|
63190
|
+
function planStoredMinFaceConfidencePurge(raw) {
|
|
63191
|
+
return planRetiredKeyPurge(raw, STORED_MIN_FACE_CONFIDENCE_KEY);
|
|
63099
63192
|
}
|
|
63100
63193
|
/**
|
|
63101
63194
|
* Map a detection-frame face short side to the 0..1 `sizeScore` the
|
|
@@ -63384,7 +63477,7 @@ var FaceRecognizer = class {
|
|
|
63384
63477
|
async processFrame(input) {
|
|
63385
63478
|
const { settings } = input;
|
|
63386
63479
|
for (const t of input.tracked) if (t.resurrectionScene === "multi-subject") this.quarantineHeldFace(input.deviceId, t.trackId);
|
|
63387
|
-
const candidates = input.tracked.filter((t) => Array.isArray(t.embedding) && t.embedding.length > 0 && typeof t.embeddingModelId === "string" &&
|
|
63480
|
+
const candidates = input.tracked.filter((t) => Array.isArray(t.embedding) && t.embedding.length > 0 && typeof t.embeddingModelId === "string" && (t.nativeFaceShortSidePx ?? (t.faceBbox ? Math.min(t.faceBbox.w, t.faceBbox.h) : void 0) ?? Number.POSITIVE_INFINITY) >= settings.minFacePx);
|
|
63388
63481
|
if (candidates.length === 0) return;
|
|
63389
63482
|
this.deps.logger.debug("face: frame candidates", {
|
|
63390
63483
|
tags: { deviceId: input.deviceId },
|
|
@@ -72951,6 +73044,58 @@ function hasKeyFrame(source) {
|
|
|
72951
73044
|
}
|
|
72952
73045
|
//#endregion
|
|
72953
73046
|
//#region src/pipeline-analytics/rebuild-source-loader.ts
|
|
73047
|
+
function refused(reason) {
|
|
73048
|
+
return {
|
|
73049
|
+
bbox: null,
|
|
73050
|
+
boxSource: {
|
|
73051
|
+
kind: "refused",
|
|
73052
|
+
reason
|
|
73053
|
+
}
|
|
73054
|
+
};
|
|
73055
|
+
}
|
|
73056
|
+
function normaliseMeasured(box) {
|
|
73057
|
+
if (box.frameWidth <= 0 || box.frameHeight <= 0 || box.w <= 0 || box.h <= 0) return null;
|
|
73058
|
+
return {
|
|
73059
|
+
x: box.x / box.frameWidth,
|
|
73060
|
+
y: box.y / box.frameHeight,
|
|
73061
|
+
w: box.w / box.frameWidth,
|
|
73062
|
+
h: box.h / box.frameHeight
|
|
73063
|
+
};
|
|
73064
|
+
}
|
|
73065
|
+
/**
|
|
73066
|
+
* The box measured on THIS key frame: its own `subjectBox`, else the track
|
|
73067
|
+
* position at exactly its instant, else a named refusal. Never another
|
|
73068
|
+
* frame's box (D303).
|
|
73069
|
+
*/
|
|
73070
|
+
async function keyFrameBox(deps, trackId, keyFrame) {
|
|
73071
|
+
const own = (await deps.media.listSubjectBoxesByOwner("track", trackId)).find((row) => row.mediaId === keyFrame.mediaId);
|
|
73072
|
+
if (own !== void 0) {
|
|
73073
|
+
const bbox = normaliseMeasured(own.subjectBox);
|
|
73074
|
+
if (bbox !== null) return {
|
|
73075
|
+
bbox,
|
|
73076
|
+
boxSource: { kind: "subjectBox" }
|
|
73077
|
+
};
|
|
73078
|
+
}
|
|
73079
|
+
const track = await deps.tracks.getPersistedByTrackId(trackId);
|
|
73080
|
+
if (track === null) return refused("track-row-missing");
|
|
73081
|
+
const { frameWidth, frameHeight } = track;
|
|
73082
|
+
if (frameWidth === void 0 || frameHeight === void 0) return refused("track-frame-size-unknown");
|
|
73083
|
+
const at = track.positions.find((p) => p.timestamp === keyFrame.timestamp);
|
|
73084
|
+
if (at === void 0) return refused("no-position-at-key-frame");
|
|
73085
|
+
const bbox = normaliseMeasured({
|
|
73086
|
+
...at.bbox,
|
|
73087
|
+
frameWidth,
|
|
73088
|
+
frameHeight
|
|
73089
|
+
});
|
|
73090
|
+
if (bbox === null) return refused("no-position-at-key-frame");
|
|
73091
|
+
return {
|
|
73092
|
+
bbox,
|
|
73093
|
+
boxSource: { kind: "positions" }
|
|
73094
|
+
};
|
|
73095
|
+
}
|
|
73096
|
+
function hasBox(event) {
|
|
73097
|
+
return event.bbox !== void 0 && event.bbox.w > 0 && event.bbox.h > 0;
|
|
73098
|
+
}
|
|
72954
73099
|
/**
|
|
72955
73100
|
* Assemble one track's rebuild inputs, reading at most ONE blob.
|
|
72956
73101
|
*
|
|
@@ -72958,7 +73103,8 @@ function hasKeyFrame(source) {
|
|
|
72958
73103
|
* to describe, and the caller counts it. A track WITH an event but WITHOUT a
|
|
72959
73104
|
* key frame still returns a source (with `keyFrame: null`) so the caller's
|
|
72960
73105
|
* `missingKeyFrame` counter stays the one place that decision is made; no blob
|
|
72961
|
-
* is read in that case either.
|
|
73106
|
+
* is read in that case either. A key frame with no box measured on it returns
|
|
73107
|
+
* `bbox: null` and a named refusal, also without reading the blob.
|
|
72962
73108
|
*/
|
|
72963
73109
|
async function loadRebuildSource(deps, trackId) {
|
|
72964
73110
|
const media = await deps.media.listInfoByOwner("track", trackId);
|
|
@@ -72966,26 +73112,44 @@ async function loadRebuildSource(deps, trackId) {
|
|
|
72966
73112
|
const cropInfo = media.find((m) => m.kind === "thumbnail");
|
|
72967
73113
|
const peak = await deps.events.peakForTrack(trackId);
|
|
72968
73114
|
const events = await deps.events.queryObjectByTrackIds([trackId]);
|
|
72969
|
-
const best = events.find((e) => String(e.id) === peak.bestEventId) ?? events[0];
|
|
73115
|
+
const best = events.find((e) => String(e.id) === peak.bestEventId) ?? events.find(hasBox) ?? events[0];
|
|
72970
73116
|
if (best === void 0) return null;
|
|
72971
73117
|
const common = {
|
|
72972
73118
|
trackId,
|
|
72973
73119
|
deviceId: best.deviceId,
|
|
72974
|
-
timestamp: best.timestamp,
|
|
72975
73120
|
className: best.className,
|
|
72976
73121
|
confidence: best.confidence ?? 0,
|
|
72977
|
-
bbox: normaliseEventBbox(best),
|
|
72978
73122
|
...cropInfo !== void 0 ? { mediaId: cropInfo.mediaId } : {}
|
|
72979
73123
|
};
|
|
72980
|
-
if (keyFrameInfo === void 0)
|
|
73124
|
+
if (keyFrameInfo === void 0) {
|
|
73125
|
+
const bbox = normaliseEventBbox(best);
|
|
73126
|
+
return {
|
|
73127
|
+
...common,
|
|
73128
|
+
timestamp: best.timestamp,
|
|
73129
|
+
bbox,
|
|
73130
|
+
boxSource: bbox !== null ? { kind: "event" } : {
|
|
73131
|
+
kind: "refused",
|
|
73132
|
+
reason: "event-without-box"
|
|
73133
|
+
},
|
|
73134
|
+
keyFrame: null
|
|
73135
|
+
};
|
|
73136
|
+
}
|
|
73137
|
+
const box = await keyFrameBox(deps, trackId, keyFrameInfo);
|
|
73138
|
+
const keyed = {
|
|
72981
73139
|
...common,
|
|
73140
|
+
timestamp: keyFrameInfo.timestamp,
|
|
73141
|
+
bbox: box.bbox,
|
|
73142
|
+
boxSource: box.boxSource,
|
|
73143
|
+
keyFrameMediaId: keyFrameInfo.mediaId
|
|
73144
|
+
};
|
|
73145
|
+
if (box.bbox === null) return {
|
|
73146
|
+
...keyed,
|
|
72982
73147
|
keyFrame: null
|
|
72983
73148
|
};
|
|
72984
73149
|
const keyFrameFile = await deps.media.getById(keyFrameInfo.mediaId);
|
|
72985
73150
|
return {
|
|
72986
|
-
...
|
|
72987
|
-
keyFrame: keyFrameFile ? Buffer.from(keyFrameFile.base64, "base64") : null
|
|
72988
|
-
keyFrameMediaId: keyFrameInfo.mediaId
|
|
73151
|
+
...keyed,
|
|
73152
|
+
keyFrame: keyFrameFile ? Buffer.from(keyFrameFile.base64, "base64") : null
|
|
72989
73153
|
};
|
|
72990
73154
|
}
|
|
72991
73155
|
//#endregion
|
|
@@ -83534,7 +83698,7 @@ function buildGlobalSettingsSchema(cap) {
|
|
|
83534
83698
|
addonId: "pipeline-analytics",
|
|
83535
83699
|
action: "embedding.rebuildStatus",
|
|
83536
83700
|
buttonLabel: "Check progress",
|
|
83537
|
-
successMessage: "{modelId} → {index}: indexed {indexed} · scanned {scanned} · rebuilt {rebuilt} · no key frame {missingKeyFrame} · not runnable {notRunnable} · failed {failed}"
|
|
83701
|
+
successMessage: "{modelId} → {index}: indexed {indexed} · scanned {scanned} · rebuilt {rebuilt} · no key frame {missingKeyFrame} · no box {missingBbox} · no event {missingEvent} · not runnable {notRunnable} · failed {failed}"
|
|
83538
83702
|
},
|
|
83539
83703
|
{
|
|
83540
83704
|
type: "addon-action-button",
|
|
@@ -84086,16 +84250,6 @@ function buildGlobalSettingsSchema(cap) {
|
|
|
84086
84250
|
step: .01,
|
|
84087
84251
|
default: FACE_DEFAULTS.margin
|
|
84088
84252
|
},
|
|
84089
|
-
{
|
|
84090
|
-
type: "number",
|
|
84091
|
-
key: "minFaceConfidence",
|
|
84092
|
-
label: "Min face confidence",
|
|
84093
|
-
description: "Minimum face-detection confidence (0–1) for a face to be considered.",
|
|
84094
|
-
min: 0,
|
|
84095
|
-
max: 1,
|
|
84096
|
-
step: .05,
|
|
84097
|
-
default: FACE_DEFAULTS.minFaceConfidence
|
|
84098
|
-
},
|
|
84099
84253
|
{
|
|
84100
84254
|
type: "number",
|
|
84101
84255
|
key: "minFacePx",
|
|
@@ -94875,6 +95029,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
94875
95029
|
const deviceIds = await this.retentionDeviceIds();
|
|
94876
95030
|
await this.migrateRetiredRetentionSettings(deviceIds);
|
|
94877
95031
|
await this.purgeStoredSuggestionThreshold(deviceIds);
|
|
95032
|
+
await this.purgeStoredMinFaceConfidence(deviceIds);
|
|
94878
95033
|
await this.runTrackRetentionSweep(deviceIds, now);
|
|
94879
95034
|
const eventStore = this.eventStore;
|
|
94880
95035
|
const sensorEventStore = this.sensorEventStore;
|
|
@@ -95002,6 +95157,80 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
95002
95157
|
* this process, and which devices have. One announcement, not a heartbeat. */
|
|
95003
95158
|
storedSuggestionCheckedGlobal = false;
|
|
95004
95159
|
storedSuggestionCheckedDevices = /* @__PURE__ */ new Set();
|
|
95160
|
+
storedMinFaceConfidenceCheckedGlobal = false;
|
|
95161
|
+
storedMinFaceConfidenceCheckedDevices = /* @__PURE__ */ new Set();
|
|
95162
|
+
/**
|
|
95163
|
+
* One-time: announce the recognizer face-confidence bar D662 retired, then
|
|
95164
|
+
* unset it — globally and per device. Same shape as
|
|
95165
|
+
* {@link purgeStoredSuggestionThreshold}: absence of the key is the marker,
|
|
95166
|
+
* the write goes through `updateGlobalSettings` / `writeDeviceStore`, and the
|
|
95167
|
+
* patch unsets with `undefined`.
|
|
95168
|
+
*
|
|
95169
|
+
* Why it must leave the store and not merely go unread: the bar compared the
|
|
95170
|
+
* DETECTOR's score without knowing which detector produced it, so its units
|
|
95171
|
+
* changed under it when YuNet became the default (D645). A number left in the
|
|
95172
|
+
* blob is an authority the next reader who greps for it would re-adopt — at a
|
|
95173
|
+
* scale nobody can name. The hub carried an interim 0.85 set by hand on
|
|
95174
|
+
* 2026-09-27; the one bar in force is now the detector model's own floor.
|
|
95175
|
+
*/
|
|
95176
|
+
async purgeStoredMinFaceConfidence(deviceIds) {
|
|
95177
|
+
const settings = this.ctxIfReady?.settings;
|
|
95178
|
+
if (!settings) return;
|
|
95179
|
+
if (!this.storedMinFaceConfidenceCheckedGlobal) {
|
|
95180
|
+
this.storedMinFaceConfidenceCheckedGlobal = true;
|
|
95181
|
+
try {
|
|
95182
|
+
const plan = planStoredMinFaceConfidencePurge(await this.resolveGlobalStore());
|
|
95183
|
+
if (plan !== null) {
|
|
95184
|
+
this.announceRetiredFaceConfidenceBar({
|
|
95185
|
+
scope: "global",
|
|
95186
|
+
was: plan.was
|
|
95187
|
+
});
|
|
95188
|
+
await this.updateGlobalSettings(plan.patch);
|
|
95189
|
+
}
|
|
95190
|
+
} catch (err) {
|
|
95191
|
+
this.storedMinFaceConfidenceCheckedGlobal = false;
|
|
95192
|
+
this.ctx.logger.warn("face confidence bar purge failed — will retry", { meta: {
|
|
95193
|
+
scope: "global",
|
|
95194
|
+
error: String(err)
|
|
95195
|
+
} });
|
|
95196
|
+
}
|
|
95197
|
+
}
|
|
95198
|
+
for (const deviceId of deviceIds) {
|
|
95199
|
+
if (this.storedMinFaceConfidenceCheckedDevices.has(deviceId)) continue;
|
|
95200
|
+
this.storedMinFaceConfidenceCheckedDevices.add(deviceId);
|
|
95201
|
+
try {
|
|
95202
|
+
const plan = planStoredMinFaceConfidencePurge(await this.readDeviceBlob(deviceId));
|
|
95203
|
+
if (plan === null) continue;
|
|
95204
|
+
this.announceRetiredFaceConfidenceBar({
|
|
95205
|
+
scope: "device",
|
|
95206
|
+
was: plan.was,
|
|
95207
|
+
deviceId
|
|
95208
|
+
});
|
|
95209
|
+
await settings.writeDeviceStore(deviceId, plan.patch);
|
|
95210
|
+
this.rawDeviceBlobMirror.invalidate(deviceId);
|
|
95211
|
+
} catch (err) {
|
|
95212
|
+
this.storedMinFaceConfidenceCheckedDevices.delete(deviceId);
|
|
95213
|
+
this.ctx.logger.warn("face confidence bar purge failed — will retry", {
|
|
95214
|
+
tags: { deviceId },
|
|
95215
|
+
meta: {
|
|
95216
|
+
scope: "device",
|
|
95217
|
+
error: String(err)
|
|
95218
|
+
}
|
|
95219
|
+
});
|
|
95220
|
+
}
|
|
95221
|
+
}
|
|
95222
|
+
}
|
|
95223
|
+
announceRetiredFaceConfidenceBar(found) {
|
|
95224
|
+
this.ctx.logger.warn("face confidence bar RETIRED — the detector model floor on the runner is the one bar now", {
|
|
95225
|
+
...found.deviceId !== void 0 ? { tags: { deviceId: found.deviceId } } : {},
|
|
95226
|
+
meta: {
|
|
95227
|
+
scope: found.scope,
|
|
95228
|
+
setting: STORED_MIN_FACE_CONFIDENCE_KEY,
|
|
95229
|
+
wasSetTo: found.was,
|
|
95230
|
+
why: "the recognizer compared the detector score without knowing which detector ran; after YuNet became the default its 0.5 was SCRFD’s bar on YuNet’s scale (D662)."
|
|
95231
|
+
}
|
|
95232
|
+
});
|
|
95233
|
+
}
|
|
95005
95234
|
/**
|
|
95006
95235
|
* One-time: announce the suggestion floor D222 retired, then unset it —
|
|
95007
95236
|
* globally and per device.
|
|
@@ -97056,6 +97285,15 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
97056
97285
|
refusal: "stores-unavailable"
|
|
97057
97286
|
};
|
|
97058
97287
|
}
|
|
97288
|
+
const force = input.force === true;
|
|
97289
|
+
if (force && input.maxTracks === void 0) {
|
|
97290
|
+
this.ctx.logger.warn("rebuildObjectEmbeddings: refusing a force pass with no maxTracks", { meta: { refusal: "force-requires-max-tracks" } });
|
|
97291
|
+
return {
|
|
97292
|
+
started: false,
|
|
97293
|
+
alreadyRunning: false,
|
|
97294
|
+
refusal: "force-requires-max-tracks"
|
|
97295
|
+
};
|
|
97296
|
+
}
|
|
97059
97297
|
const confirmation = await this.getClusterPinConfirmer(api, "clip-rebuild").confirm();
|
|
97060
97298
|
if (confirmation.kind === "refused") {
|
|
97061
97299
|
this.ctx.logger.warn("rebuildObjectEmbeddings: the cluster CLIP model is not confirmed — refusing to start a pass that cannot pin one", { meta: { refusal: confirmation.reason } });
|
|
@@ -97099,16 +97337,17 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
97099
97337
|
logger: this.ctx.logger
|
|
97100
97338
|
}));
|
|
97101
97339
|
const deps = {
|
|
97102
|
-
listTrackIdPage: async (cursor) => trackStore.queryRecentIds({
|
|
97340
|
+
listTrackIdPage: async (cursor) => trackStore.queryRecentIds(rebuildTrackPageQuery({
|
|
97103
97341
|
deviceIds,
|
|
97104
97342
|
...input.since !== void 0 ? { since: input.since } : {},
|
|
97105
97343
|
...input.until !== void 0 ? { until: input.until } : {},
|
|
97106
97344
|
...cursor !== null ? { cursor } : {},
|
|
97107
97345
|
limit: REBUILD_PAGE_SIZE
|
|
97108
|
-
}),
|
|
97346
|
+
})),
|
|
97109
97347
|
loadSource: (trackId) => loadRebuildSource({
|
|
97110
97348
|
media: mediaStore,
|
|
97111
|
-
events: eventStore
|
|
97349
|
+
events: eventStore,
|
|
97350
|
+
tracks: trackStore
|
|
97112
97351
|
}, trackId),
|
|
97113
97352
|
recoverKeyFrame: async (source) => {
|
|
97114
97353
|
const recovered = await recordedStills.recover(source.deviceId, source.timestamp, RECOVERED_KEY_FRAME_MAX_WIDTH);
|
|
@@ -97134,7 +97373,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
97134
97373
|
if (split === null) return null;
|
|
97135
97374
|
return {
|
|
97136
97375
|
outOfSpace: split.outOfSpaceIds,
|
|
97137
|
-
alreadyInSpace: split.inSpace
|
|
97376
|
+
alreadyInSpace: split.inSpace,
|
|
97377
|
+
inSpace: split.inSpaceIds
|
|
97138
97378
|
};
|
|
97139
97379
|
},
|
|
97140
97380
|
logger: {
|
|
@@ -97146,6 +97386,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
97146
97386
|
running: true,
|
|
97147
97387
|
modelId,
|
|
97148
97388
|
index,
|
|
97389
|
+
force,
|
|
97149
97390
|
startedAtMs: Date.now(),
|
|
97150
97391
|
progress: {
|
|
97151
97392
|
scanned: 0,
|
|
@@ -97154,6 +97395,14 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
97154
97395
|
recoveredKeyFrame: 0,
|
|
97155
97396
|
missingEvent: 0,
|
|
97156
97397
|
missingBbox: 0,
|
|
97398
|
+
boxSource: {
|
|
97399
|
+
subjectBox: 0,
|
|
97400
|
+
positions: 0,
|
|
97401
|
+
event: 0,
|
|
97402
|
+
refused: 0
|
|
97403
|
+
},
|
|
97404
|
+
forcedInSpace: 0,
|
|
97405
|
+
skippedOutOfSpace: 0,
|
|
97157
97406
|
alreadyInSpace: 0,
|
|
97158
97407
|
notRunnable: 0,
|
|
97159
97408
|
noCapableNode: 0,
|
|
@@ -97161,6 +97410,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
97161
97410
|
}
|
|
97162
97411
|
};
|
|
97163
97412
|
rebuildObjectEmbeddings(deps, {
|
|
97413
|
+
force,
|
|
97164
97414
|
...input.maxTracks !== void 0 ? { maxTracks: input.maxTracks } : {},
|
|
97165
97415
|
...input.pacingMs !== void 0 ? { pacingMs: input.pacingMs } : {},
|
|
97166
97416
|
onProgress: (progress) => {
|
|
@@ -97172,6 +97422,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
97172
97422
|
running: false,
|
|
97173
97423
|
modelId,
|
|
97174
97424
|
index,
|
|
97425
|
+
force,
|
|
97175
97426
|
startedAtMs: this.rebuildState.startedAtMs ?? Date.now(),
|
|
97176
97427
|
finishedAtMs: Date.now(),
|
|
97177
97428
|
progress: outcome,
|
|
@@ -97187,6 +97438,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
97187
97438
|
running: false,
|
|
97188
97439
|
modelId,
|
|
97189
97440
|
index,
|
|
97441
|
+
force,
|
|
97190
97442
|
startedAtMs: this.rebuildState.startedAtMs ?? Date.now(),
|
|
97191
97443
|
finishedAtMs: Date.now(),
|
|
97192
97444
|
error: String(err)
|
|
@@ -97201,7 +97453,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
97201
97453
|
modelId,
|
|
97202
97454
|
index,
|
|
97203
97455
|
deviceId: input.deviceId ?? "all",
|
|
97204
|
-
maxTracks: input.maxTracks ?? "unbounded"
|
|
97456
|
+
maxTracks: input.maxTracks ?? "unbounded",
|
|
97457
|
+
force
|
|
97205
97458
|
} });
|
|
97206
97459
|
return {
|
|
97207
97460
|
started: true,
|
|
@@ -98203,8 +98456,18 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
98203
98456
|
running: state.running,
|
|
98204
98457
|
scanned: p?.scanned ?? 0,
|
|
98205
98458
|
rebuilt: p?.rebuilt ?? 0,
|
|
98206
|
-
missingKeyFrame:
|
|
98459
|
+
missingKeyFrame: p?.missingKeyFrame ?? 0,
|
|
98460
|
+
missingEvent: p?.missingEvent ?? 0,
|
|
98207
98461
|
missingBbox: p?.missingBbox ?? 0,
|
|
98462
|
+
boxSource: p?.boxSource ?? {
|
|
98463
|
+
subjectBox: 0,
|
|
98464
|
+
positions: 0,
|
|
98465
|
+
event: 0,
|
|
98466
|
+
refused: 0
|
|
98467
|
+
},
|
|
98468
|
+
alreadyInSpace: p?.alreadyInSpace ?? 0,
|
|
98469
|
+
force: state.force ?? null,
|
|
98470
|
+
forcedInSpace: p?.forcedInSpace ?? 0,
|
|
98208
98471
|
notRunnable: p?.notRunnable ?? 0,
|
|
98209
98472
|
noCapableNode: p?.noCapableNode ?? 0,
|
|
98210
98473
|
failed: p?.failed ?? 0,
|