@camstack/addon-post-analysis 1.2.626 → 1.2.628
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-FGmg0uYz.js → clip-model-registry-CK0QHBLo.js} +6823 -1590
- package/dist/{clip-model-registry-DAWGt4j9.mjs → clip-model-registry-CXp8hOtz.mjs} +6818 -1591
- 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-Biy-u2yt.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-BSMQI14W.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CC5fsXdm.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-DdDfkgWU.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-4lybsFX0.mjs → hostInit-DZur54eI.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +259 -136
- package/dist/pipeline-analytics/index.mjs +259 -136
- 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-yap5surJ.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-_Ip2ZGVX.mjs +0 -26
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_clip_model_registry = require("../clip-model-registry-
|
|
5
|
+
const require_clip_model_registry = require("../clip-model-registry-CK0QHBLo.js");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
node_fs = require_clip_model_registry.__toESM(node_fs, 1);
|
|
8
8
|
let node_path = require("node:path");
|
|
@@ -9913,7 +9913,6 @@ var SCENE_LATCH_SPEC = {
|
|
|
9913
9913
|
fromRecord: latchFromRecord,
|
|
9914
9914
|
deviceIdOf: (row) => row.deviceId
|
|
9915
9915
|
};
|
|
9916
|
-
SCENE_LATCH_SPEC.fromRecord, SCENE_LATCH_SPEC.toValue, SCENE_LATCH_SPEC.deviceIdOf;
|
|
9917
9916
|
/**
|
|
9918
9917
|
* The two ledgers behind one façade. Callers never see the split, but they can
|
|
9919
9918
|
* never accidentally write one when they meant the other either: the config
|
|
@@ -16404,6 +16403,18 @@ function gapDistance(a, b) {
|
|
|
16404
16403
|
if (last === void 0 || first === void 0 || first.timestamp < last.timestamp) return 0;
|
|
16405
16404
|
return Math.sqrt((first.x - last.x) ** 2 + (first.y - last.y) ** 2);
|
|
16406
16405
|
}
|
|
16406
|
+
/**
|
|
16407
|
+
* WHERE a fused track was detected (D683 L2 fusion): it OPENED where its
|
|
16408
|
+
* earliest-born piece opened and CLOSED where its latest-seen piece was last
|
|
16409
|
+
* sighted — the same span `firstSeen` / `lastSeen` take, decided by the times
|
|
16410
|
+
* rather than by which piece survived (an absorbed piece can overlap and end
|
|
16411
|
+
* first). The placements of the pieces in between are not kept: the row
|
|
16412
|
+
* answers "where did this subject start and end", and a hop in the middle is
|
|
16413
|
+
* the `inference device selection` log's to tell. A piece with no placement
|
|
16414
|
+
* never erases the other's.
|
|
16415
|
+
*/
|
|
16416
|
+
var earlierOpened = (a, b) => b.firstSeen < a.firstSeen ? b.openedPlacement ?? a.openedPlacement : a.openedPlacement ?? b.openedPlacement;
|
|
16417
|
+
var laterClosed = (a, b) => b.lastSeen >= a.lastSeen ? b.closedPlacement ?? a.closedPlacement : a.closedPlacement ?? b.closedPlacement;
|
|
16407
16418
|
var TRACK_MERGE_RULES = {
|
|
16408
16419
|
trackId: survivor$1("trackId"),
|
|
16409
16420
|
deviceId: survivor$1("deviceId"),
|
|
@@ -16444,6 +16455,8 @@ var TRACK_MERGE_RULES = {
|
|
|
16444
16455
|
hasRider: either$1("hasRider"),
|
|
16445
16456
|
closedReason: survivor$1("closedReason"),
|
|
16446
16457
|
provenance: survivor$1("provenance"),
|
|
16458
|
+
openedPlacement: earlierOpened,
|
|
16459
|
+
closedPlacement: laterClosed,
|
|
16447
16460
|
movedProbe: mergedMovedProbe,
|
|
16448
16461
|
keptAtPromotion: (a, b) => a.keptAtPromotion === true || b.keptAtPromotion === true ? true : void 0
|
|
16449
16462
|
};
|
|
@@ -16485,6 +16498,8 @@ var TRACK_MERGE_KEYS = [
|
|
|
16485
16498
|
"hasRider",
|
|
16486
16499
|
"closedReason",
|
|
16487
16500
|
"provenance",
|
|
16501
|
+
"openedPlacement",
|
|
16502
|
+
"closedPlacement",
|
|
16488
16503
|
"movedProbe",
|
|
16489
16504
|
"keptAtPromotion"
|
|
16490
16505
|
];
|
|
@@ -16821,7 +16836,15 @@ var TRACKS_COLUMNS = [
|
|
|
16821
16836
|
{
|
|
16822
16837
|
name: "observations",
|
|
16823
16838
|
type: "INTEGER"
|
|
16824
|
-
})
|
|
16839
|
+
}),
|
|
16840
|
+
{
|
|
16841
|
+
name: "openedPlacement",
|
|
16842
|
+
type: "JSON"
|
|
16843
|
+
},
|
|
16844
|
+
{
|
|
16845
|
+
name: "closedPlacement",
|
|
16846
|
+
type: "JSON"
|
|
16847
|
+
}
|
|
16825
16848
|
];
|
|
16826
16849
|
/**
|
|
16827
16850
|
* The columns `rowToTrack` reads, per projection — the SELECT list the store
|
|
@@ -16968,7 +16991,9 @@ function cloneTrack(t) {
|
|
|
16968
16991
|
...t.provenance !== void 0 ? {
|
|
16969
16992
|
frameWidth: t.provenance.frameWidth,
|
|
16970
16993
|
frameHeight: t.provenance.frameHeight
|
|
16971
|
-
} : {}
|
|
16994
|
+
} : {},
|
|
16995
|
+
...t.openedPlacement !== void 0 ? { openedPlacement: { ...t.openedPlacement } } : {},
|
|
16996
|
+
...t.closedPlacement !== void 0 ? { closedPlacement: { ...t.closedPlacement } } : {}
|
|
16972
16997
|
};
|
|
16973
16998
|
}
|
|
16974
16999
|
/** Ids per set-based `benchPinned` statement — well under SQLite's bound
|
|
@@ -17116,7 +17141,11 @@ var TrackStore = class {
|
|
|
17116
17141
|
active: true,
|
|
17117
17142
|
lastSnapshotAt: 0,
|
|
17118
17143
|
movedProbe: stepMovedProbe(EMPTY_MOVED_PROBE, params.position.bbox),
|
|
17119
|
-
...params.provenance !== void 0 ? { provenance: params.provenance } : {}
|
|
17144
|
+
...params.provenance !== void 0 ? { provenance: params.provenance } : {},
|
|
17145
|
+
...params.placement !== void 0 ? {
|
|
17146
|
+
openedPlacement: params.placement,
|
|
17147
|
+
closedPlacement: params.placement
|
|
17148
|
+
} : {}
|
|
17120
17149
|
};
|
|
17121
17150
|
}
|
|
17122
17151
|
const existing = this.active.get(params.trackId);
|
|
@@ -17130,6 +17159,7 @@ var TrackStore = class {
|
|
|
17130
17159
|
const last = existing.positions[existing.positions.length - 1];
|
|
17131
17160
|
const dist = last ? Math.sqrt((params.position.x - last.x) ** 2 + (params.position.y - last.y) ** 2) : 0;
|
|
17132
17161
|
existing.lastSeen = params.timestamp;
|
|
17162
|
+
if (params.placement !== void 0) existing.closedPlacement = params.placement;
|
|
17133
17163
|
existing.totalDistance += dist;
|
|
17134
17164
|
existing.state = params.state;
|
|
17135
17165
|
existing.movedProbe = stepMovedProbe(existing.movedProbe, params.position.bbox);
|
|
@@ -17155,7 +17185,11 @@ var TrackStore = class {
|
|
|
17155
17185
|
active: true,
|
|
17156
17186
|
lastSnapshotAt: 0,
|
|
17157
17187
|
movedProbe: stepMovedProbe(EMPTY_MOVED_PROBE, params.position.bbox),
|
|
17158
|
-
...params.provenance !== void 0 ? { provenance: params.provenance } : {}
|
|
17188
|
+
...params.provenance !== void 0 ? { provenance: params.provenance } : {},
|
|
17189
|
+
...params.placement !== void 0 ? {
|
|
17190
|
+
openedPlacement: params.placement,
|
|
17191
|
+
closedPlacement: params.placement
|
|
17192
|
+
} : {}
|
|
17159
17193
|
};
|
|
17160
17194
|
this.active.set(params.trackId, fresh);
|
|
17161
17195
|
return fresh;
|
|
@@ -18906,7 +18940,9 @@ var TrackStore = class {
|
|
|
18906
18940
|
frameWidth: dims.w,
|
|
18907
18941
|
frameHeight: dims.h
|
|
18908
18942
|
} : {},
|
|
18909
|
-
...t.modelId !== void 0 ? { modelId: t.modelId } : {}
|
|
18943
|
+
...t.modelId !== void 0 ? { modelId: t.modelId } : {},
|
|
18944
|
+
...t.openedPlacement !== void 0 ? { openedPlacement: t.openedPlacement } : {},
|
|
18945
|
+
...t.closedPlacement !== void 0 ? { closedPlacement: t.closedPlacement } : {}
|
|
18910
18946
|
}
|
|
18911
18947
|
});
|
|
18912
18948
|
}
|
|
@@ -18971,6 +19007,8 @@ var TrackStore = class {
|
|
|
18971
19007
|
* string read, absent stays absent. */
|
|
18972
19008
|
const previewMissReason = data["previewMissReason"];
|
|
18973
19009
|
const modelId = data["modelId"];
|
|
19010
|
+
const openedPlacement = require_clip_model_registry.TrackPlacementSchema.safeParse(data["openedPlacement"]);
|
|
19011
|
+
const closedPlacement = require_clip_model_registry.TrackPlacementSchema.safeParse(data["closedPlacement"]);
|
|
18974
19012
|
const frameWidth = data["frameWidth"];
|
|
18975
19013
|
const frameHeight = data["frameHeight"];
|
|
18976
19014
|
const envMinX = data["envMinX"];
|
|
@@ -19023,7 +19061,9 @@ var TrackStore = class {
|
|
|
19023
19061
|
...typeof frameWidth === "number" && typeof frameHeight === "number" ? {
|
|
19024
19062
|
frameWidth,
|
|
19025
19063
|
frameHeight
|
|
19026
|
-
} : {}
|
|
19064
|
+
} : {},
|
|
19065
|
+
...openedPlacement.success ? { openedPlacement: openedPlacement.data } : {},
|
|
19066
|
+
...closedPlacement.success ? { closedPlacement: closedPlacement.data } : {}
|
|
19027
19067
|
});
|
|
19028
19068
|
}
|
|
19029
19069
|
};
|
|
@@ -22287,6 +22327,8 @@ function proposalOrigin(source, index, facts) {
|
|
|
22287
22327
|
...facts.modelId !== void 0 ? { modelId: facts.modelId } : {}
|
|
22288
22328
|
};
|
|
22289
22329
|
}
|
|
22330
|
+
//#endregion
|
|
22331
|
+
//#region src/pipeline-analytics/retrain/retrain-taxonomy.ts
|
|
22290
22332
|
var MACRO_SET = new Set([
|
|
22291
22333
|
"person",
|
|
22292
22334
|
"vehicle",
|
|
@@ -25867,7 +25909,6 @@ var NC_ALERTS_SPEC = {
|
|
|
25867
25909
|
equalFact: (held, incoming) => held.alerting === incoming.alerting,
|
|
25868
25910
|
deviceIdOf: (row) => deviceIdOf(row.subject)
|
|
25869
25911
|
};
|
|
25870
|
-
NC_ALERTS_SPEC.fromRecord, NC_ALERTS_SPEC.toValue, NC_ALERTS_SPEC.deviceIdOf;
|
|
25871
25912
|
/**
|
|
25872
25913
|
* Which row the boot settle keeps for one subject observed inside the window
|
|
25873
25914
|
* (D698's rule, applied to the alert ledger).
|
|
@@ -30600,7 +30641,6 @@ var NC_DEVICE_PRUNES_SPEC = {
|
|
|
30600
30641
|
deviceIdOf: (row) => row.subjectKind === "device" ? Number(row.subject) : void 0,
|
|
30601
30642
|
loadLimit: LOAD_LIMIT$1
|
|
30602
30643
|
};
|
|
30603
|
-
NC_DEVICE_PRUNES_SPEC.fromRecord, NC_DEVICE_PRUNES_SPEC.toValue, NC_DEVICE_PRUNES_SPEC.deviceIdOf;
|
|
30604
30644
|
/** The outcomes that mean "this last reference was already dealt with". */
|
|
30605
30645
|
var KEPT_OUTCOMES = new Set(["kept-disabled", "kept"]);
|
|
30606
30646
|
var NcPruneLedger = class {
|
|
@@ -45607,7 +45647,6 @@ var NC_ALERT_EPISODES_SPEC = {
|
|
|
45607
45647
|
};
|
|
45608
45648
|
}
|
|
45609
45649
|
};
|
|
45610
|
-
NC_ALERT_EPISODES_SPEC.fromRecord, NC_ALERT_EPISODES_SPEC.toValue;
|
|
45611
45650
|
var NcAlertEpisodeLedger = class {
|
|
45612
45651
|
ledger;
|
|
45613
45652
|
constructor(deps) {
|
|
@@ -45765,6 +45804,8 @@ function occupancyClassWarning(className) {
|
|
|
45765
45804
|
if (className === void 0 || require_clip_model_registry.isDetectionMacroClass(className)) return null;
|
|
45766
45805
|
return `⚠ “${className}” is a sub-type, not a macro class: this counter is always 0 (use ${[...require_clip_model_registry.DETECTION_MACRO_CLASSES].join(" / ")})`;
|
|
45767
45806
|
}
|
|
45807
|
+
//#endregion
|
|
45808
|
+
//#region src/notification-center/occupancy-store.ts
|
|
45768
45809
|
/**
|
|
45769
45810
|
* The mechanics, declared once.
|
|
45770
45811
|
*
|
|
@@ -45916,7 +45957,6 @@ function recordToRow(key, data) {
|
|
|
45916
45957
|
updatedAt
|
|
45917
45958
|
};
|
|
45918
45959
|
}
|
|
45919
|
-
NC_OCCUPANCY_SPEC.fromRecord, NC_OCCUPANCY_SPEC.toValue, NC_OCCUPANCY_SPEC.deviceIdOf;
|
|
45920
45960
|
//#endregion
|
|
45921
45961
|
//#region src/notification-center/outbox.ts
|
|
45922
45962
|
/**
|
|
@@ -48387,7 +48427,6 @@ var NC_SNOOZES_SPEC = {
|
|
|
48387
48427
|
},
|
|
48388
48428
|
loadLimit: 1e3
|
|
48389
48429
|
};
|
|
48390
|
-
NC_SNOOZES_SPEC.fromRecord, NC_SNOOZES_SPEC.toValue;
|
|
48391
48430
|
var NcSnoozeStore = class {
|
|
48392
48431
|
windows;
|
|
48393
48432
|
/** The `snooze-suppressed` records kind (events.db): the counters. */
|
|
@@ -52485,7 +52524,6 @@ var NC_SYSTEM_STATE_SPEC = {
|
|
|
52485
52524
|
},
|
|
52486
52525
|
deviceIdOf: (row) => row.deviceId
|
|
52487
52526
|
};
|
|
52488
|
-
NC_SYSTEM_STATE_SPEC.fromRecord, NC_SYSTEM_STATE_SPEC.toValue, NC_SYSTEM_STATE_SPEC.deviceIdOf;
|
|
52489
52527
|
/** The hub's own node id when an update row names none. */
|
|
52490
52528
|
var HUB_NODE = "hub";
|
|
52491
52529
|
function isUpdateTarget(value) {
|
|
@@ -53571,6 +53609,8 @@ var NcStateSummaryScheduler = class {
|
|
|
53571
53609
|
}
|
|
53572
53610
|
}
|
|
53573
53611
|
};
|
|
53612
|
+
//#endregion
|
|
53613
|
+
//#region src/notification-center/state-summary/state-summary-stamps.ts
|
|
53574
53614
|
var SPEC = {
|
|
53575
53615
|
collection: "notification-center:state-summary-stamps",
|
|
53576
53616
|
columns: [
|
|
@@ -53618,7 +53658,6 @@ var SPEC = {
|
|
|
53618
53658
|
},
|
|
53619
53659
|
loadLimit: 1e4
|
|
53620
53660
|
};
|
|
53621
|
-
SPEC.fromRecord, SPEC.toValue;
|
|
53622
53661
|
var NcStateSummaryStampStore = class {
|
|
53623
53662
|
ledger;
|
|
53624
53663
|
constructor(deps) {
|
|
@@ -74847,8 +74886,8 @@ var TrackCloser = class {
|
|
|
74847
74886
|
}
|
|
74848
74887
|
});
|
|
74849
74888
|
}
|
|
74850
|
-
/** Emit the
|
|
74851
|
-
*
|
|
74889
|
+
/** Emit the thin `TrackEnded` event + the unified lifecycle `end` event
|
|
74890
|
+
* (the FULL final summary — fires ONCE per real track). */
|
|
74852
74891
|
emitEndEvents(t, duration, trackerPeakConfidence, keyFrameMediaId, summary) {
|
|
74853
74892
|
this.deps.emitTrackEnded({
|
|
74854
74893
|
deviceId: t.deviceId,
|
|
@@ -74889,6 +74928,16 @@ function trackProvenanceOf(frame) {
|
|
|
74889
74928
|
};
|
|
74890
74929
|
}
|
|
74891
74930
|
//#endregion
|
|
74931
|
+
//#region src/pipeline-analytics/pipeline/track-placement.ts
|
|
74932
|
+
function trackPlacementOf(frame, nodeId) {
|
|
74933
|
+
if (nodeId.length === 0) return void 0;
|
|
74934
|
+
return {
|
|
74935
|
+
nodeId,
|
|
74936
|
+
...frame.rootDeviceKey !== void 0 && frame.rootDeviceKey.length > 0 ? { deviceKey: frame.rootDeviceKey } : {},
|
|
74937
|
+
...frame.rootModelId !== void 0 && frame.rootModelId.length > 0 ? { modelId: frame.rootModelId } : {}
|
|
74938
|
+
};
|
|
74939
|
+
}
|
|
74940
|
+
//#endregion
|
|
74892
74941
|
//#region src/pipeline-analytics/pipeline/best-detection-tracker.ts
|
|
74893
74942
|
/**
|
|
74894
74943
|
* `BestDetectionTracker` — the SINGLE canonical policy for "the best detection
|
|
@@ -79164,22 +79213,22 @@ function buildTapeDeleteDeps(src) {
|
|
|
79164
79213
|
removeFile: src.removeFile
|
|
79165
79214
|
};
|
|
79166
79215
|
}
|
|
79167
|
-
function unavailable(reason) {
|
|
79216
|
+
function unavailable$1(reason) {
|
|
79168
79217
|
return {
|
|
79169
79218
|
status: "unavailable",
|
|
79170
79219
|
reason
|
|
79171
79220
|
};
|
|
79172
79221
|
}
|
|
79173
79222
|
async function releaseOrUnavailable(deps, tapeId, queue) {
|
|
79174
|
-
if (typeof deps === "string") return unavailable(deps);
|
|
79223
|
+
if (typeof deps === "string") return unavailable$1(deps);
|
|
79175
79224
|
return queue.run((signal) => releaseTape(deps, tapeId, signal), { name: "release" });
|
|
79176
79225
|
}
|
|
79177
79226
|
async function deleteOrUnavailable(deps, tapeId, queue) {
|
|
79178
|
-
if (typeof deps === "string") return unavailable(deps);
|
|
79227
|
+
if (typeof deps === "string") return unavailable$1(deps);
|
|
79179
79228
|
return queue.run((signal) => deleteTape(deps, tapeId, signal), { name: "delete" });
|
|
79180
79229
|
}
|
|
79181
79230
|
async function reconcileOrUnavailable(deps, queue) {
|
|
79182
|
-
if (typeof deps === "string") return unavailable(deps);
|
|
79231
|
+
if (typeof deps === "string") return unavailable$1(deps);
|
|
79183
79232
|
return queue.run((signal) => reconcileTapePins(deps, signal), { name: "reconcile" });
|
|
79184
79233
|
}
|
|
79185
79234
|
/**
|
|
@@ -83743,6 +83792,9 @@ function isConfirmationCompatible(trackClassName, detectionMacroClass) {
|
|
|
83743
83792
|
if (track === "other" || det === "other") return true;
|
|
83744
83793
|
return track === det;
|
|
83745
83794
|
}
|
|
83795
|
+
function isSessionDetectorUnavailable(answer) {
|
|
83796
|
+
return answer !== null && "unavailable" in answer;
|
|
83797
|
+
}
|
|
83746
83798
|
var undecided = (candidate, reason) => ({
|
|
83747
83799
|
trackId: candidate.trackId,
|
|
83748
83800
|
verdict: "undecided",
|
|
@@ -83765,7 +83817,7 @@ async function runConfirmation(candidate, config, deps, exhausted) {
|
|
|
83765
83817
|
const carried = candidate.evidenceCrop ?? null;
|
|
83766
83818
|
if (carried) {
|
|
83767
83819
|
const verdict = await measure(candidate, carried, config, deps, "carried");
|
|
83768
|
-
if (verdict.verdict === "confirmed" || verdict.reason === "redetect-error") return verdict;
|
|
83820
|
+
if (verdict.verdict === "confirmed" || verdict.reason === "redetect-error" || verdict.reason === "session-device-unavailable") return verdict;
|
|
83769
83821
|
}
|
|
83770
83822
|
let crop = await deps.fetchCrop(candidate);
|
|
83771
83823
|
let cropSource = "native";
|
|
@@ -83787,11 +83839,14 @@ async function measure(candidate, crop, config, deps, cropSource) {
|
|
|
83787
83839
|
deps.keepCrop?.(candidate, crop, cropSource);
|
|
83788
83840
|
const detections = await deps.redetect(crop);
|
|
83789
83841
|
if (detections === null) return undecided(candidate, "redetect-error");
|
|
83842
|
+
if (isSessionDetectorUnavailable(detections)) return undecided(candidate, "session-device-unavailable");
|
|
83790
83843
|
let best;
|
|
83791
83844
|
let bestIncompatible;
|
|
83792
83845
|
for (const d of detections) if (isConfirmationCompatible(candidate.className, d.macroClass)) {
|
|
83793
83846
|
if (!best || d.score > best.score) best = d;
|
|
83794
|
-
} else if (
|
|
83847
|
+
} else if (d.refusedByDetectorFloor !== true) {
|
|
83848
|
+
if (!bestIncompatible || d.score > bestIncompatible.score) bestIncompatible = d;
|
|
83849
|
+
}
|
|
83795
83850
|
const bar = barFor(candidate, config, deps);
|
|
83796
83851
|
const confirmed = best !== void 0 && best.score >= bar;
|
|
83797
83852
|
if (!confirmed && cropSource !== "native") return undecided(candidate, cropSource === "fallback" ? "fallback-inconclusive" : "carried-inconclusive");
|
|
@@ -83799,7 +83854,7 @@ async function measure(candidate, crop, config, deps, cropSource) {
|
|
|
83799
83854
|
return {
|
|
83800
83855
|
trackId: candidate.trackId,
|
|
83801
83856
|
verdict: confirmed ? "confirmed" : "suppressed",
|
|
83802
|
-
reason: confirmed ? "confirmed" :
|
|
83857
|
+
reason: confirmed ? "confirmed" : suppressionReason(best, bestIncompatible),
|
|
83803
83858
|
className: candidate.className,
|
|
83804
83859
|
appliedMinConfidence: bar,
|
|
83805
83860
|
cropSource,
|
|
@@ -83812,6 +83867,16 @@ async function measure(candidate, crop, config, deps, cropSource) {
|
|
|
83812
83867
|
};
|
|
83813
83868
|
}
|
|
83814
83869
|
/**
|
|
83870
|
+
* Why a measured native crop said no — first matching rule wins (D922). The
|
|
83871
|
+
* best compatible box is under the gate's bar either way; `below-detector-floor`
|
|
83872
|
+
* says the detector's own floor had refused it too (D925).
|
|
83873
|
+
*/
|
|
83874
|
+
function suppressionReason(best, bestIncompatible) {
|
|
83875
|
+
if (best !== void 0) return best.refusedByDetectorFloor === true ? "below-detector-floor" : "scored-below-threshold";
|
|
83876
|
+
if (bestIncompatible !== void 0) return "incompatible-class";
|
|
83877
|
+
return "no-detection";
|
|
83878
|
+
}
|
|
83879
|
+
/**
|
|
83815
83880
|
* The incompatible best becomes a secondary subject when it clears the SAME
|
|
83816
83881
|
* bar the candidate faced and can be placed in the frame. The crop-normalised
|
|
83817
83882
|
* box is scaled into the crop's frame rectangle — the one derivation the
|
|
@@ -86557,11 +86622,9 @@ function faceSizeScore(detectionFrameShortSidePx) {
|
|
|
86557
86622
|
return detectionFrameShortSidePx / FACE_SIZE_SCORE_REFERENCE_PX;
|
|
86558
86623
|
}
|
|
86559
86624
|
//#endregion
|
|
86560
|
-
//#region src/pipeline-analytics/face-
|
|
86625
|
+
//#region src/pipeline-analytics/face-recognizer.ts
|
|
86561
86626
|
/** The recognizer's step id — the attribution a face identity label carries. */
|
|
86562
86627
|
var FACE_RECOGNIZER_STEP_ID = "face-recognizer";
|
|
86563
|
-
//#endregion
|
|
86564
|
-
//#region src/pipeline-analytics/face-recognizer.ts
|
|
86565
86628
|
/** At most one "dropping imageless track" log per this interval, per recognizer. */
|
|
86566
86629
|
var FACE_IMAGELESS_LOG_THROTTLE_MS = 6e4;
|
|
86567
86630
|
/** At most one 'embedding magnitude' sample line per device per this interval. */
|
|
@@ -93000,11 +93063,119 @@ function buildBirthDecisionRecord(input) {
|
|
|
93000
93063
|
decidedByBirthEvidence: input.decidedByBirthEvidence,
|
|
93001
93064
|
bestScore: input.bestScore ?? null,
|
|
93002
93065
|
appliedMinConfidence: input.appliedMinConfidence ?? null,
|
|
93066
|
+
cropSource: input.cropSource ?? null,
|
|
93067
|
+
detectorModelId: input.detector?.modelId ?? null,
|
|
93068
|
+
detectorDeviceKey: input.detector?.deviceKey ?? null,
|
|
93069
|
+
detectorNodeId: input.detector?.nodeId ?? null,
|
|
93003
93070
|
firstSeen,
|
|
93004
93071
|
...latency
|
|
93005
93072
|
};
|
|
93006
93073
|
}
|
|
93007
93074
|
//#endregion
|
|
93075
|
+
//#region src/pipeline-analytics/confirmation-redetect-result.ts
|
|
93076
|
+
/** Map a re-detect result to the gate's input; `null` when it carried no detections array. */
|
|
93077
|
+
function toConfirmationDetections(result) {
|
|
93078
|
+
const detections = result?.detections;
|
|
93079
|
+
if (!result || !detections) return null;
|
|
93080
|
+
const cropWidth = result.width ?? 0;
|
|
93081
|
+
const cropHeight = result.height ?? 0;
|
|
93082
|
+
const kept = detections.map((d) => ({
|
|
93083
|
+
macroClass: d.macroClass,
|
|
93084
|
+
score: d.score,
|
|
93085
|
+
...d.bbox !== void 0 && cropWidth > 0 && cropHeight > 0 ? { bbox: {
|
|
93086
|
+
x: d.bbox.x / cropWidth,
|
|
93087
|
+
y: d.bbox.y / cropHeight,
|
|
93088
|
+
w: d.bbox.width / cropWidth,
|
|
93089
|
+
h: d.bbox.height / cropHeight
|
|
93090
|
+
} } : {}
|
|
93091
|
+
}));
|
|
93092
|
+
const refused = (result.discarded ?? []).filter((d) => d.reason === "below-threshold").map((d) => ({
|
|
93093
|
+
macroClass: d.macroClass,
|
|
93094
|
+
score: d.score,
|
|
93095
|
+
refusedByDetectorFloor: true
|
|
93096
|
+
}));
|
|
93097
|
+
return [...kept, ...refused];
|
|
93098
|
+
}
|
|
93099
|
+
//#endregion
|
|
93100
|
+
//#region src/pipeline-analytics/confirmation-session-detector.ts
|
|
93101
|
+
/**
|
|
93102
|
+
* The detector the birth confirmation gate re-judges a birth WITH: the
|
|
93103
|
+
* session's own (D925).
|
|
93104
|
+
*
|
|
93105
|
+
* A birth is a claim made by one detector — the root model of the session that
|
|
93106
|
+
* produced the frame, on the inference-device pool it ran on. The gate asks
|
|
93107
|
+
* whether that claim holds on better pixels, so it must ask the SAME detector:
|
|
93108
|
+
* a different model has a different score scale and a different floor, and its
|
|
93109
|
+
* "no" says nothing about the claim. It used to ask the node's global default
|
|
93110
|
+
* (`getGlobalSteps`), which on a Coral node meant a CPU `yolov9t` re-judging an
|
|
93111
|
+
* `edgetpu` model's births.
|
|
93112
|
+
*
|
|
93113
|
+
* The identity rides the frame result (`rootStepId` / `rootModelId` /
|
|
93114
|
+
* `rootDeviceKey`, stamped by the executor with what it RAN), and the node is
|
|
93115
|
+
* the frame handle's — the same node the crop is cut on, so no new bytes cross
|
|
93116
|
+
* anywhere.
|
|
93117
|
+
*
|
|
93118
|
+
* When that detector cannot answer — no identity on the frame (an onboard
|
|
93119
|
+
* detector), the device in backoff or failed, or the executor running anything
|
|
93120
|
+
* other than exactly that model on exactly that pool — the answer is
|
|
93121
|
+
* `session-device-unavailable`: NO measurement. The gate defers the birth and
|
|
93122
|
+
* admits it once the deferral is exhausted. Another model is never asked.
|
|
93123
|
+
*
|
|
93124
|
+
* PURE apart from the injected `run`, so the matrix is testable without an
|
|
93125
|
+
* executor.
|
|
93126
|
+
*/
|
|
93127
|
+
/** The session detector named by a frame, or `null` when the frame names none in full. */
|
|
93128
|
+
function sessionDetectorOf(frame, nodeId) {
|
|
93129
|
+
const { rootStepId, rootModelId, rootDeviceKey } = frame;
|
|
93130
|
+
if (!rootStepId || !rootModelId || !rootDeviceKey || !nodeId) return null;
|
|
93131
|
+
return {
|
|
93132
|
+
stepId: rootStepId,
|
|
93133
|
+
modelId: rootModelId,
|
|
93134
|
+
deviceKey: rootDeviceKey,
|
|
93135
|
+
nodeId
|
|
93136
|
+
};
|
|
93137
|
+
}
|
|
93138
|
+
/**
|
|
93139
|
+
* The executor's refusal of a device it will not dispatch to: the liveness
|
|
93140
|
+
* refusal (`InferenceDeviceUnusableError`), a device key whose backend this
|
|
93141
|
+
* node does not know, or a pinned pool that cannot serve. Read from the
|
|
93142
|
+
* message because the error crosses a process boundary without its class.
|
|
93143
|
+
*/
|
|
93144
|
+
var DEVICE_REFUSAL = /inference device ".+" is (failed|backoff)|unknown backend|device-not-servable|model-not-servable/;
|
|
93145
|
+
/** Re-detect a crop with the session detector, or say why it could not. */
|
|
93146
|
+
async function redetectWithSessionDetector(detector, cropJpeg, deviceId, run) {
|
|
93147
|
+
if (detector === null) return unavailable("the frame names no session detector");
|
|
93148
|
+
let result;
|
|
93149
|
+
try {
|
|
93150
|
+
result = await run({
|
|
93151
|
+
steps: [{
|
|
93152
|
+
addonId: detector.stepId,
|
|
93153
|
+
modelId: detector.modelId,
|
|
93154
|
+
enabled: true
|
|
93155
|
+
}],
|
|
93156
|
+
image: new Uint8Array(cropJpeg),
|
|
93157
|
+
deviceId,
|
|
93158
|
+
plane: "frame",
|
|
93159
|
+
deviceKey: detector.deviceKey
|
|
93160
|
+
}, detector.nodeId);
|
|
93161
|
+
} catch (err) {
|
|
93162
|
+
const message = require_clip_model_registry.errMsg(err);
|
|
93163
|
+
if (DEVICE_REFUSAL.test(message)) return unavailable(message);
|
|
93164
|
+
return {
|
|
93165
|
+
answer: null,
|
|
93166
|
+
error: message
|
|
93167
|
+
};
|
|
93168
|
+
}
|
|
93169
|
+
if (result !== null && (result.rootModelId !== detector.modelId || result.rootDeviceKey !== detector.deviceKey)) return unavailable(`ran ${result.rootModelId ?? "an unnamed model"} on ${result.rootDeviceKey ?? "an unnamed pool"}, not ${detector.modelId} on ${detector.deviceKey}`);
|
|
93170
|
+
return { answer: toConfirmationDetections(result) };
|
|
93171
|
+
}
|
|
93172
|
+
function unavailable(detail) {
|
|
93173
|
+
return { answer: {
|
|
93174
|
+
unavailable: "session-device-unavailable",
|
|
93175
|
+
detail
|
|
93176
|
+
} };
|
|
93177
|
+
}
|
|
93178
|
+
//#endregion
|
|
93008
93179
|
//#region src/pipeline-analytics/pipeline/birth-evidence-store.ts
|
|
93009
93180
|
/**
|
|
93010
93181
|
* The pixels a birth arrived with, held for as long as its deferral can last —
|
|
@@ -93914,7 +94085,6 @@ var PHANTOM_CELLS_SPEC = {
|
|
|
93914
94085
|
},
|
|
93915
94086
|
deviceIdOf: (row) => row.deviceId
|
|
93916
94087
|
};
|
|
93917
|
-
PHANTOM_CELLS_SPEC.fromRecord, PHANTOM_CELLS_SPEC.toValue, PHANTOM_CELLS_SPEC.deviceIdOf;
|
|
93918
94088
|
/**
|
|
93919
94089
|
* The durable cell memory. Reads answer from RAM only (D49) — a gate that
|
|
93920
94090
|
* consulted SQLite would be a gate that fails when SQLite is slow.
|
|
@@ -94114,7 +94284,6 @@ var PACKAGE_BACKGROUND_SPEC = {
|
|
|
94114
94284
|
},
|
|
94115
94285
|
deviceIdOf: (row) => row.deviceId
|
|
94116
94286
|
};
|
|
94117
|
-
PACKAGE_BACKGROUND_SPEC.fromRecord, PACKAGE_BACKGROUND_SPEC.toValue, PACKAGE_BACKGROUND_SPEC.deviceIdOf;
|
|
94118
94287
|
/**
|
|
94119
94288
|
* The durable ghost-cycle memory. Reads answer from RAM only (D49); writes go
|
|
94120
94289
|
* write-behind — a lost write costs one under-counted cycle, which is the
|
|
@@ -96679,7 +96848,6 @@ var STATIONARY_EVIDENCE_SPEC = {
|
|
|
96679
96848
|
},
|
|
96680
96849
|
deviceIdOf: (row) => row.deviceId
|
|
96681
96850
|
};
|
|
96682
|
-
STATIONARY_EVIDENCE_SPEC.fromRecord, STATIONARY_EVIDENCE_SPEC.toValue, STATIONARY_EVIDENCE_SPEC.deviceIdOf;
|
|
96683
96851
|
var StationaryEvidenceLedger = class {
|
|
96684
96852
|
ledger;
|
|
96685
96853
|
spec = STATIONARY_EVIDENCE_SPEC;
|
|
@@ -97214,7 +97382,6 @@ var STATIONARY_SPEC = {
|
|
|
97214
97382
|
fromRecord: rowToEntry,
|
|
97215
97383
|
deviceIdOf: (entry) => entry.deviceId
|
|
97216
97384
|
};
|
|
97217
|
-
STATIONARY_SPEC.fromRecord, STATIONARY_SPEC.toValue, STATIONARY_SPEC.deviceIdOf;
|
|
97218
97385
|
var StationaryObjectRegistry = class {
|
|
97219
97386
|
/** Entry ids per device — an INDEX over the ledger's mirror, not a second
|
|
97220
97387
|
* copy of it. The entries themselves live in exactly one place. */
|
|
@@ -113295,9 +113462,6 @@ var KEYFRAME_CROP_MIN_SUBJECT_IOU = .5;
|
|
|
113295
113462
|
* evidence" and the temporal bound takes over. */
|
|
113296
113463
|
var KEYFRAME_CROP_MAX_SAMPLE_GAP_MS = 1e3;
|
|
113297
113464
|
var SETTINGS_CACHE_TTL_MS = 5e3;
|
|
113298
|
-
/** TTL for the per-node confirmation-gate detector-step cache (the node's
|
|
113299
|
-
* default object-detector step rarely changes). */
|
|
113300
|
-
var CONFIRMATION_DETECTOR_CACHE_TTL_MS = 6e4;
|
|
113301
113465
|
/** Padding applied to a birth box before re-detecting it — a little context
|
|
113302
113466
|
* around the subject improves the confirmation detector's recall. */
|
|
113303
113467
|
var CONFIRMATION_CROP_PADDING = .15;
|
|
@@ -114085,11 +114249,6 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
114085
114249
|
trackingSettingsCache = this.settingsCaches.registerDeviceCache("tracking", SETTINGS_CACHE_TTL_MS);
|
|
114086
114250
|
/** Per-device confirmation-gate settings cache (default off), TTL-mirrored. */
|
|
114087
114251
|
confirmationGateSettingsCache = this.settingsCaches.registerDeviceCache("confirmation-gate", SETTINGS_CACHE_TTL_MS);
|
|
114088
|
-
/** Per-node detector-step cache for the confirmation gate's re-detection —
|
|
114089
|
-
* the node's default root object-detector reduced to a single childless
|
|
114090
|
-
* step, resolved lazily from `pipelineExecutor.getGlobalSteps` and reused.
|
|
114091
|
-
* NOT part of the settings-cache hub: node-keyed, not device-keyed. */
|
|
114092
|
-
confirmationDetectorStepByNode = /* @__PURE__ */ new Map();
|
|
114093
114252
|
faceSettingsCache = this.settingsCaches.registerDeviceCache("face", SETTINGS_CACHE_TTL_MS);
|
|
114094
114253
|
/** GLOBAL face-recognition master switch (addon store), TTL-cached. */
|
|
114095
114254
|
faceGlobalEnabledCache = this.settingsCaches.registerGlobalCache("face-global-enabled", SETTINGS_CACHE_TTL_MS);
|
|
@@ -118359,7 +118518,6 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
118359
118518
|
this.settingsCaches.clearAll();
|
|
118360
118519
|
this.rawDeviceBlobMirror.invalidateAll();
|
|
118361
118520
|
this.rawGlobalStoreMirror.invalidate();
|
|
118362
|
-
this.confirmationDetectorStepByNode.clear();
|
|
118363
118521
|
this.trackStore?.clearAll();
|
|
118364
118522
|
this.stationaryRegistry = null;
|
|
118365
118523
|
this.bindingCache?.clearAll();
|
|
@@ -118465,7 +118623,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
118465
118623
|
}
|
|
118466
118624
|
});
|
|
118467
118625
|
}
|
|
118468
|
-
await this.processFrame(deviceId, frame, data.source ?? "pipeline", data.frameHandle, data.detailSteps, data.occasion ?? "session");
|
|
118626
|
+
await this.processFrame(deviceId, frame, data.source ?? "pipeline", data.frameHandle, data.detailSteps, data.occasion ?? "session", data.nodeId);
|
|
118469
118627
|
}
|
|
118470
118628
|
/**
|
|
118471
118629
|
* Run one detection frame through the analysis layers for a given
|
|
@@ -118739,7 +118897,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
118739
118897
|
}
|
|
118740
118898
|
});
|
|
118741
118899
|
}
|
|
118742
|
-
async processFrame(deviceId, frame, source, rawFrameHandle, detailSteps, occasion = "session") {
|
|
118900
|
+
async processFrame(deviceId, frame, source, rawFrameHandle, detailSteps, occasion = "session", producerNodeId = "") {
|
|
118743
118901
|
if (this.shuttingDown) return;
|
|
118744
118902
|
if (detailSteps !== void 0) this.detailStepsByDevice.set(deviceId, detailSteps);
|
|
118745
118903
|
if (!await this.bindingCache.isActive(deviceId)) {
|
|
@@ -118926,6 +119084,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
118926
119084
|
const currentTrackIds = /* @__PURE__ */ new Set();
|
|
118927
119085
|
const positionsCountById = /* @__PURE__ */ new Map();
|
|
118928
119086
|
const provenance = trackProvenanceOf(frame);
|
|
119087
|
+
const placement = trackPlacementOf(frame, producerNodeId);
|
|
118929
119088
|
for (const t of result.tracked) {
|
|
118930
119089
|
currentTrackIds.add(t.trackId);
|
|
118931
119090
|
if (this.suppressedBirths.isRejected(key, t.trackId)) continue;
|
|
@@ -118950,7 +119109,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
118950
119109
|
},
|
|
118951
119110
|
zones: t.zones,
|
|
118952
119111
|
state: t.state,
|
|
118953
|
-
...provenance !== void 0 ? { provenance } : {}
|
|
119112
|
+
...provenance !== void 0 ? { provenance } : {},
|
|
119113
|
+
...placement !== void 0 ? { placement } : {}
|
|
118954
119114
|
});
|
|
118955
119115
|
positionsCountById.set(t.trackId, upserted.positions.length);
|
|
118956
119116
|
}
|
|
@@ -119015,6 +119175,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
119015
119175
|
this.birthEvidence.remember(key, id, Buffer.from(t.birthEvidence.jpegBase64, "base64"), exhaustionNowMs);
|
|
119016
119176
|
}
|
|
119017
119177
|
const withBirthEvidence = /* @__PURE__ */ new Set();
|
|
119178
|
+
const sessionDetector = frameHandle ? sessionDetectorOf(frame, frameHandle.nodeId) : null;
|
|
119018
119179
|
const run = await this.confirmTrackBirths(bornCandidates.map(({ id, t }) => {
|
|
119019
119180
|
const evidenceCrop = this.birthEvidence.get(key, id, exhaustionNowMs);
|
|
119020
119181
|
if (evidenceCrop !== null) withBirthEvidence.add(id);
|
|
@@ -119030,7 +119191,9 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
119030
119191
|
source,
|
|
119031
119192
|
frameHandle,
|
|
119032
119193
|
frameWidth: result.frameWidth,
|
|
119033
|
-
frameHeight: result.frameHeight
|
|
119194
|
+
frameHeight: result.frameHeight,
|
|
119195
|
+
sessionDetector,
|
|
119196
|
+
attemptsFor: (trackId) => this.deferredBirths.attemptsFor(key, trackId)
|
|
119034
119197
|
}, exhaustedIds);
|
|
119035
119198
|
const outcome = run.outcome;
|
|
119036
119199
|
const gateNowMs = Date.now();
|
|
@@ -119085,6 +119248,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
119085
119248
|
matchedThisFrame: t.matchedThisFrame,
|
|
119086
119249
|
birthEvidenceAvailable: withBirthEvidence.has(id),
|
|
119087
119250
|
decision: run.decisions.get(id),
|
|
119251
|
+
sessionDetector,
|
|
119088
119252
|
decidedAtMs: gateNowMs,
|
|
119089
119253
|
firstSeen: this.trackStore?.peekActive(id)?.firstSeen ?? null
|
|
119090
119254
|
});
|
|
@@ -119144,16 +119308,25 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
119144
119308
|
processor.markSuppressed(id);
|
|
119145
119309
|
this.trackStore?.dropActive(id);
|
|
119146
119310
|
this.clearLiveTrackState(deviceId, id);
|
|
119147
|
-
|
|
119148
|
-
|
|
119149
|
-
|
|
119150
|
-
|
|
119151
|
-
|
|
119152
|
-
|
|
119153
|
-
|
|
119154
|
-
|
|
119155
|
-
|
|
119156
|
-
|
|
119311
|
+
const suppression = run.decisions.get(id);
|
|
119312
|
+
log.info("birth suppressed — track record retracted", {
|
|
119313
|
+
tags: { deviceId },
|
|
119314
|
+
meta: {
|
|
119315
|
+
trackId: id,
|
|
119316
|
+
className: t.className,
|
|
119317
|
+
source,
|
|
119318
|
+
reason: suppression?.reason ?? null,
|
|
119319
|
+
bestScore: suppression?.bestScore ?? null,
|
|
119320
|
+
appliedMinConfidence: suppression?.appliedMinConfidence ?? null,
|
|
119321
|
+
cropSource: suppression?.cropSource ?? null,
|
|
119322
|
+
attempts: deferredAttempts,
|
|
119323
|
+
...wasDeferred ? {
|
|
119324
|
+
wasDeferred,
|
|
119325
|
+
deferredForMs,
|
|
119326
|
+
deferredAttempts
|
|
119327
|
+
} : {}
|
|
119328
|
+
}
|
|
119329
|
+
});
|
|
119157
119330
|
continue;
|
|
119158
119331
|
}
|
|
119159
119332
|
if (wasDeferred && exhaustedIds.has(id)) log.warn("birth allowed unmeasured — deferral exhausted, no crop available", { meta: {
|
|
@@ -119845,88 +120018,30 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
119845
120018
|
return this.confirmationGateSettingsCache.get(deviceId, (id) => this.readDeviceSettings(id, resolveConfirmationGateSettings));
|
|
119846
120019
|
}
|
|
119847
120020
|
/**
|
|
119848
|
-
*
|
|
119849
|
-
*
|
|
119850
|
-
*
|
|
119851
|
-
*
|
|
120021
|
+
* Re-run object detection on a confirmation crop JPEG with the SESSION'S
|
|
120022
|
+
* detector (D925): the root model the birth's frame ran, on the device pool
|
|
120023
|
+
* it ran on, pinned to that frame's node — the node the crop is cut on, so
|
|
120024
|
+
* no new bytes cross anywhere. A session detector that cannot answer is
|
|
120025
|
+
* `session-device-unavailable` (no measurement, the birth defers); another
|
|
120026
|
+
* model is never asked. An inference failure is `null` (`redetect-error`).
|
|
119852
120027
|
*/
|
|
119853
|
-
|
|
119854
|
-
const
|
|
119855
|
-
|
|
119856
|
-
|
|
119857
|
-
|
|
119858
|
-
|
|
119859
|
-
|
|
119860
|
-
|
|
119861
|
-
|
|
119862
|
-
|
|
119863
|
-
|
|
119864
|
-
|
|
119865
|
-
|
|
119866
|
-
|
|
119867
|
-
|
|
119868
|
-
if (cached && now < cached.expiresAt) return cached.step;
|
|
119869
|
-
let step = null;
|
|
119870
|
-
const executor = this.pipelineExecutorApi();
|
|
119871
|
-
if (executor?.getGlobalSteps) try {
|
|
119872
|
-
const steps = await executor.getGlobalSteps.query(void 0, require_clip_model_registry.nodePin(nodeId));
|
|
119873
|
-
const detector = steps?.find((s) => s.slot === "detector" && s.enabled) ?? steps?.find((s) => s.slot === "detector");
|
|
119874
|
-
if (detector) step = {
|
|
119875
|
-
addonId: detector.addonId,
|
|
119876
|
-
...detector.modelId ? { modelId: detector.modelId } : {},
|
|
119877
|
-
enabled: true
|
|
119878
|
-
};
|
|
119879
|
-
} catch (err) {
|
|
119880
|
-
this.ctx.logger.debug("confirmation gate: getGlobalSteps failed", { meta: {
|
|
119881
|
-
nodeId,
|
|
119882
|
-
error: require_clip_model_registry.errMsg(err)
|
|
119883
|
-
} });
|
|
119884
|
-
}
|
|
119885
|
-
this.confirmationDetectorStepByNode.set(nodeId, {
|
|
119886
|
-
step,
|
|
119887
|
-
expiresAt: now + CONFIRMATION_DETECTOR_CACHE_TTL_MS
|
|
120028
|
+
async redetectCropForConfirmation(detector, deviceId, cropJpeg) {
|
|
120029
|
+
const outcome = await redetectWithSessionDetector(detector, cropJpeg, deviceId, (request, nodeId) => this.ctx.api.pipelineExecutor.runPipeline.mutate({
|
|
120030
|
+
...request,
|
|
120031
|
+
steps: [...request.steps]
|
|
120032
|
+
}, require_clip_model_registry.nodePin(nodeId)));
|
|
120033
|
+
if (outcome.error !== void 0) this.ctx.logger.warn("confirmation gate: re-detection failed — birth deferred", {
|
|
120034
|
+
tags: { deviceId },
|
|
120035
|
+
meta: {
|
|
120036
|
+
error: outcome.error,
|
|
120037
|
+
...detector !== null ? {
|
|
120038
|
+
modelId: detector.modelId,
|
|
120039
|
+
deviceKey: detector.deviceKey,
|
|
120040
|
+
node: detector.nodeId
|
|
120041
|
+
} : {}
|
|
120042
|
+
}
|
|
119888
120043
|
});
|
|
119889
|
-
return
|
|
119890
|
-
}
|
|
119891
|
-
/**
|
|
119892
|
-
* Re-run object detection on a confirmation crop JPEG via the frame-owning
|
|
119893
|
-
* node's `pipelineExecutor` (pinned by `nodeId`, matching the native-crop
|
|
119894
|
-
* fetch). Returns the crop's detections, or `null` on any unavailability /
|
|
119895
|
-
* error so the gate fails open.
|
|
119896
|
-
*/
|
|
119897
|
-
async redetectCropForConfirmation(nodeId, deviceId, cropJpeg) {
|
|
119898
|
-
const step = await this.resolveConfirmationDetectorStep(nodeId);
|
|
119899
|
-
if (!step) return null;
|
|
119900
|
-
const executor = this.pipelineExecutorApi();
|
|
119901
|
-
if (!executor?.runPipeline) return null;
|
|
119902
|
-
try {
|
|
119903
|
-
const result = await executor.runPipeline.mutate({
|
|
119904
|
-
steps: [step],
|
|
119905
|
-
image: new Uint8Array(cropJpeg),
|
|
119906
|
-
deviceId,
|
|
119907
|
-
plane: "frame"
|
|
119908
|
-
}, require_clip_model_registry.nodePin(nodeId));
|
|
119909
|
-
const detections = result?.detections;
|
|
119910
|
-
if (!detections) return null;
|
|
119911
|
-
const cropWidth = result.width ?? 0;
|
|
119912
|
-
const cropHeight = result.height ?? 0;
|
|
119913
|
-
return detections.map((d) => ({
|
|
119914
|
-
macroClass: d.macroClass,
|
|
119915
|
-
score: d.score,
|
|
119916
|
-
...d.bbox !== void 0 && cropWidth > 0 && cropHeight > 0 ? { bbox: {
|
|
119917
|
-
x: d.bbox.x / cropWidth,
|
|
119918
|
-
y: d.bbox.y / cropHeight,
|
|
119919
|
-
w: d.bbox.width / cropWidth,
|
|
119920
|
-
h: d.bbox.height / cropHeight
|
|
119921
|
-
} } : {}
|
|
119922
|
-
}));
|
|
119923
|
-
} catch (err) {
|
|
119924
|
-
this.ctx.logger.debug("confirmation gate: re-detection failed — fail-open", {
|
|
119925
|
-
tags: { deviceId },
|
|
119926
|
-
meta: { error: require_clip_model_registry.errMsg(err) }
|
|
119927
|
-
});
|
|
119928
|
-
return null;
|
|
119929
|
-
}
|
|
120044
|
+
return outcome.answer;
|
|
119930
120045
|
}
|
|
119931
120046
|
/**
|
|
119932
120047
|
* Confirm a batch of track-birth candidates before they are created. Returns
|
|
@@ -119980,6 +120095,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
119980
120095
|
reason: decision?.reason ?? null,
|
|
119981
120096
|
bestScore: decision?.bestScore ?? null,
|
|
119982
120097
|
appliedMinConfidence: decision?.appliedMinConfidence ?? null,
|
|
120098
|
+
cropSource: decision?.cropSource ?? null,
|
|
120099
|
+
detector: decision !== void 0 && (decision.cropSource !== void 0 || decision.reason === "session-device-unavailable") ? input.sessionDetector ?? null : null,
|
|
119983
120100
|
decidedAtMs: input.decidedAtMs,
|
|
119984
120101
|
firstSeen: input.firstSeen,
|
|
119985
120102
|
motionOnsetAtMs,
|
|
@@ -120017,7 +120134,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
120017
120134
|
});
|
|
120018
120135
|
return allConfirmed();
|
|
120019
120136
|
}
|
|
120020
|
-
const
|
|
120137
|
+
const { sessionDetector } = params;
|
|
120021
120138
|
const candidateNativeRecovery = /* @__PURE__ */ new Map();
|
|
120022
120139
|
for (const c of candidates) if (c.nativeRecovery !== void 0) candidateNativeRecovery.set(c.trackId, c.nativeRecovery);
|
|
120023
120140
|
return {
|
|
@@ -120044,7 +120161,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
120044
120161
|
h: candidate.bbox.h
|
|
120045
120162
|
}, frameWidth, frameHeight, CONFIRMATION_CROP_PADDING, candidate.trackId, CONFIRMATION_CROP_MAX_WIDTH);
|
|
120046
120163
|
},
|
|
120047
|
-
redetect: (cropJpeg) => this.redetectCropForConfirmation(
|
|
120164
|
+
redetect: (cropJpeg) => this.redetectCropForConfirmation(sessionDetector, deviceId, cropJpeg),
|
|
120048
120165
|
keepCrop: (candidate, cropJpeg) => {
|
|
120049
120166
|
offeredCrops.set(candidate.trackId, cropJpeg);
|
|
120050
120167
|
},
|
|
@@ -120069,6 +120186,12 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
120069
120186
|
reason: decision.reason,
|
|
120070
120187
|
className: decision.className,
|
|
120071
120188
|
...decision.bestScore !== void 0 ? { bestScore: decision.bestScore } : {},
|
|
120189
|
+
...sessionDetector !== null ? {
|
|
120190
|
+
modelId: sessionDetector.modelId,
|
|
120191
|
+
deviceKey: sessionDetector.deviceKey,
|
|
120192
|
+
node: sessionDetector.nodeId
|
|
120193
|
+
} : {},
|
|
120194
|
+
attempts: params.attemptsFor(decision.trackId),
|
|
120072
120195
|
...decision.bestIncompatibleClass !== void 0 ? {
|
|
120073
120196
|
bestIncompatibleClass: decision.bestIncompatibleClass,
|
|
120074
120197
|
bestIncompatibleScore: decision.bestIncompatibleScore
|