@camstack/addon-post-analysis 1.2.654 → 1.2.656
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/CHANGELOG.md +14 -0
- package/dist/{clip-model-registry-CFQBxtE2.js → clip-model-registry-BQ_2RsIp.js} +68511 -67387
- package/dist/{clip-model-registry-BX6j2lnF.mjs → clip-model-registry-C06M8A8U.mjs} +69016 -67928
- 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-Vag6rhEh.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-8vah5-KD.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-YXyP9GJm.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-DXQUFp7P.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-gv38vKug.mjs} +1 -1
- package/dist/pipeline-analytics/{hostInit-CnvnZsmk.mjs → hostInit-0O7AUcsV.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +334 -73
- package/dist/pipeline-analytics/index.mjs +333 -72
- 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-BUwWKfHC.mjs +0 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as MAX_TRACK_RELATIONS, $i as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, $n as bundledCamstack, $r as normalizeNcAction, $t as NcTemplateVarDescriptorSchema, A as DETECTION_MACRO_CLASSES, Aa as record, Ai as sceneMonitorCapability, An as TrackPuritySchema, Ar as isAlertEpisodeOpen, At as NcAlarmConfigSchema, B as EXPORT_DENSE_MAX_RANGES, Bi as sunTimes, Bn as alertEpisodeKind, Br as isLabelSupplyStepId, Bt as NcRuleSchema, C as COCO_TO_MACRO, Ca as boolean, Ci as retrainRevisionConflictMessage, Cn as SetTrackRelationInputSchema, Cr as eventKindLabel, Ct as NC_GROUPING_MIN_SEC, D as DEFAULT_DETAIL_CROP_CONVENTION, Da as number, Di as ruleDeviceCompatCapQueries, Dn as TimelapseRulePatchSchema, Dr as gifDeriveSpeed, Dt as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, E as CoverStateSchema, Ea as looseObject, Ei as ruleBelongsToAlarm$1, En as TimelapseRuleInputSchema, Er as failureContributionCapability, Et as NC_STATE_SUMMARY_SECTION_IDS, F as EMBEDDING_REQUIREMENTS_FAILED, Fa as union, Fi as storageOccupancyCapability, Fn as activateAlarmProfile, Fr as isDetectionMacroClass, Ft as NcConditionDescriptorSchema, G as LabelAttributionSchema, Gi as systemEventSummaryScheduleOf, Gn as applySecureOnArmEdit, Gr as isSystemDelivery, Gt as NcSnoozeInputSchema, H as FULL_IMAGE_BBOX, Hi as systemEventDeliveryProblems, Hn as applyBlockingEdit, Hr as isRetiredClearKey, Ht as NcRuleUpdateInputSchema, I as EMBEDDING_REQUIREMENTS_UNAVAILABLE, Ia as unknown, Ii as subKindsOf, In as addonWidgetsSourceCapability, Ir as isDrawableSubjectPath, It as NcConditionsSchema, J as LockStateSchema, Ji as templateVarsFor, Jn as audioMetricsCapability, Jr as kebabToCamel, Jt as NcStateSummarySectionIdSchema, K as ListTrackRelationsInputSchema, Ki as systemEventSummarySplitOf, Kn as armRemovalReconcile, Kr as isSystemEventSummaryRule, Kt as NcSnoozeSchema, L as EVENT_DENSITY_BATCH_MAX, La as EventCategory, Li as subjectPathSampleFromBox, Ln as alarmDeviceSecureOnArm, Lr as isEventKindLabelKey, Lt as NcRuleActionSchema, M as DeclaredDevices, Ma as string, Mi as sensorRaisedOf, Mn as TrackRelationSchema, Mr as isAppLinkBase, Mt as NcAlarmSensorsInputSchema, N as DetectionSourceSchema, Na as templateLiteral, Ni as servedTemplateVars, Nn as TrackSideSchema, Nr as isAudioClassName, Nt as NcAlarmSensorsSchema, O as DEFAULT_EVENT_COLOR, Oa as object, Oi as ruleGroupingApplies, On as TimelapseRuleSchema, Or as gifFromMp4Args, Ot as NC_TAXONOMY, P as EMBEDDING_MODEL_FAILED, Pa as tuple, Pi as startMoverUnderClearance, Pn as TrackSourceSchema, Pr as isDefaultAlarmProfileId, Pt as NcAlarmSettingsPatchSchema, Q as MAX_TRACK_PURITIES, Qi as zoneAnalyticsCapability, Qn as buildViewerLink, Qr as ncMediaPolicyError, Qt as NcTemplatePreviewSchema, R as EVENT_KIND_BY_CAP, Ri as subjectPathSvgPoints, Rn as alarmPanelCapability, Rr as isEventOwnerType, Rt as NcRuleInputSchema, S as BucketAccumulator, Sa as array, Sn as SetTrackPurityResultSchema, Sr as ensureAlarmProfiles, St as NC_GROUPING_MAX_SEC, T as ClearTrackRelationResultSchema, Ta as literal, Ti as ruleAutoTriggersAlarm, Tn as TRACK_RELATIONS_DEFAULT_LIMIT, Tr as faceGalleryCapability, Tt as NC_SNOOZE_MAX_MINUTES, U as FailureCounters, Ui as systemEventFamilyProblems, Un as applyModeDelaysEdits, Ur as isRootSuppliableStepId, Ut as NcScheduleSchema, V as FIRST_LEVEL_MACRO_CLASSES, Vi as syncActiveAlarmProfileSettings, Vn as alertEpisodePayload, Vr as isMediaOwnerType, Vt as NcRuleTargetSchema, W as LABEL_SUPPLY_MACRO, Wi as systemEventFilterApplies, Wn as applyNonBlockingEdit, Wr as isScheduleActive, Wt as NcSharedSequenceSchema, X as MAX_BIRTH_DECISION_RECORDS, Xi as viewerLinkBaseOf, Xn as buildEventKindDescriptor, Xr as mayWriteToLocation, Xt as NcTaxonomySchema, Y as MAX_ARCHIVED_DEBUG_NOTES, Yi as vectorDimFromBase64, Yn as audioModeOf, Yr as linkedStepOf, Yt as NcSystemEventKindSchema, Z as MAX_BIRTH_LATENCY_PROXY_MS, Zi as withSystemEventClasses, Zn as buildSubjectPath, Zr as memoizePinnedFfmpeg, Zt as NcTemplatePreviewInputSchema, _ as AlarmArmModeSchema, _a as nodePin, _i as resolveDeliveryParams, _n as SCENE_DEFAULT_UNCOVERED_POLICY, _t as NC_CONFIRM_DEFAULT_TIMEOUT_MS, a as CLIP_EMBEDDING_STEP_ID, aa as BaseAddon, ai as paletteResultSchema, an as RECORDING_SOURCE_CAMSTACK_ADDON, ar as coreBlockIdFromAddonId, at as NC_ALARM_DELAY_FIELDS, b as BaseDevice, ba as ZodObject, bi as resolveModeNotifyPolicy, bn as SceneMonitorSchema, bt as NC_DEFAULT_SNOOZE_MINUTES, c as readClusterModelPinStrict, ca as InvalidRecordError, ci as pickFaceRescoreIntervalMinutes, cn as RetrainOriginSchema, cr as deleteAlarmProfile, ct as NC_ALARM_SYSTEM_EVENT_KINDS, d as APPEARANCE_BIN_COUNT, da as createEvent, di as projectSubjectPath, dn as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, dr as deriveRecordingMode, dt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, ea as canonicalHash, ei as normalizeNcCapTarget, en as OPS_LOG_DEFAULT_LIMIT, er as calendarEventLocalSpan, et as MOTION_CLOSE_AFTER_MS, f as APPEARANCE_BLOCKS, fa as customAction, fi as readDeviceStateFrom, fn as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, fr as describeSystemEventDeliveryProblem, ft as NC_CLIP_POST_ROLL_DEFAULT_SEC, g as ActionTargetResolver, ga as isDeviceScopedCap, gi as resolveClipSearchMinScore, gn as SCENE_DEFAULT_QUIET_SECONDS, gt as NC_CONFIRM_DEFAULT_MAX_IMAGE_PX, h as AUDIO_MACRO_LABELS, ha as hydrateSchema, hi as renameAlarmProfile, hn as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, hr as deviceRemovalHookCapability, ht as NC_CONDITION_CATALOG, ia as errMsg, ii as paintHex, in as RECORDING_EXPORT_MAX_READ_BYTES, ir as consumableLowPercentOf, it as NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC, j as DETECTION_PIPELINE_CAP_NAME, ja as strictObject, ji as secureActuationFor, jn as TrackRelationKindSchema, jr as isAlertEpisodeSeverity, jt as NcAlarmPostTriggeredActionSchema, k as DEFAULT_TIMELAPSE_PREVIEW_TEXT, ka as partialRecord, ki as ruleKindOf, kn as TrackPlacementSchema, kr as isAlarmControllableCap, kt as NC_TEMPLATE_VARS, l as resolveClusterModelPin, la as RECORD_MAX_DATA_BYTES, li as pipelineAnalyticsCapability, ln as RetrainStatusSchema, lr as deriveDetailCropRect, lt as NC_ALARM_TRIGGERED_MAX_SEC, m as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, ma as defineRecordKinds, mi as readTimelapseGeneratedAt, mn as SCENE_DEFAULT_CHECK_INTERVAL_SEC, mr as deviceAttentionKind, mt as NC_CLIP_RETENTION_MAX_SEC, na as isSourceCap, ni as notificationRulesCapability, nn as PackageLlmVerdictSchema, nr as cloneAlarmSettings, nt as MotionTriggeredBySchema, o as CLUSTER_MODEL_OWNER_ADDON_ID, oa as CAP_ADVANCE_FIELDS, oi as parseAlertEpisodePayload, on as RebuildObjectEmbeddingsRefusalSchema, or as cosineSimilarity$1, ot as NC_ALARM_DELAY_MAX_SEC, p as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, pa as defineCustomActions, pi as readMotionTriggeredBy, pn as SCENE_DEFAULT_ANCHOR_THRESHOLD, pr as describeSystemEventFamilyProblem, pt as NC_CLIP_PRE_ROLL_DEFAULT_SEC, q as ListTrackRelationsResultSchema, qi as templateCarriesSummary, qn as assertTimelapseCadences, qr as isVectorIndexDimConflict, qt as NcSnoozeSuppressedSchema, ra as DeviceType, ri as occupancyScope, rr as consumableFormOf, rt as NC_ALARM_DEFAULT_PROFILE_ID, s as FACE_EMBEDDING_STEP_ID, sa as CamProfileSchema, sn as RetrainDismissedSchema, sr as createAlarmProfile, st as NC_ALARM_NOTIFY_FIELDS, t as BUILTIN_CLIP_MODELS, ta as evaluateSensorEdge, ti as normalizeNcMediaPolicy, tn as OpsLogEntrySchema, tr as classifyRetrainReview, tt as MediaFileKindEnum, u as ACTION_TARGET_INVALIDATION_EVENTS, ua as RECORD_QUERY_MAX, ui as plateGalleryCapability, un as RetrainVerdictSubjectSchema, ur as derivePostTriggeredAction, ut as NC_AUDIO_CONFIRM_HITS_DEFAULT, v as ArchivedDebugNoteSchema, vi as resolveLocationMode, vn as SCENE_DIVERGED, vr as embeddingRefusalOf, vt as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, w as ClearTrackRelationInputSchema, wa as discriminatedUnion, wi as rootSupplyServes, wn as TIMELAPSE_DENSE_FLOOR_SEC, wr as evictionPolicyOfLocation, wt as NC_SENSOR_TRANSITION_KINDS, x as BirthDecisionRecordSchema, xa as _enum, xi as resolveNcMediaImage, xn as SetTrackPurityInputSchema, xr as encodeVectorBase64, xt as NC_GROUPING_DEFAULT_SEC, y as BIRTH_DECISION_DEFAULT_LIMIT, ya as sleep$1, yi as resolveModeDelays, yn as SCENE_RESET_RECAPTURES, yt as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, z as EVENT_OWNER_TYPES, zi as summarizeReview, zn as alertEpisodeId, zr as isKnownTemplateVar, zt as NcRulePatchSchema } from "../clip-model-registry-C06M8A8U.mjs";
|
|
2
2
|
import { t as __exportAll } from "../embedding-encoder/index.mjs";
|
|
3
3
|
import * as fs$1 from "node:fs";
|
|
4
4
|
import { createWriteStream, promises } from "node:fs";
|
|
@@ -888,7 +888,9 @@ function describeGrant(grant) {
|
|
|
888
888
|
return grant.action === "disarm" ? "Alarm disarmed" : `Alarm armed${grant.mode !== void 0 ? ` (${grant.mode})` : ""}`;
|
|
889
889
|
case "addon-update": return `${grant.packages.length} addon update(s) on ${grant.nodeId}`;
|
|
890
890
|
case "server-update": return `Server update on ${grant.nodeId}`;
|
|
891
|
-
case "detection-verdict":
|
|
891
|
+
case "detection-verdict":
|
|
892
|
+
if (grant.verdict === "wrong-label") return "Marked label wrong, class right — kept for retraining";
|
|
893
|
+
return grant.verdict === "correct" ? "Marked correct — kept for retraining" : grant.suggestedClass === void 0 ? "Marked wrong — kept for retraining" : `Marked wrong, it was a ${grant.suggestedClass} — kept for retraining`;
|
|
892
894
|
}
|
|
893
895
|
}
|
|
894
896
|
/** The audit line's `meta`, per family. A snooze that logged a `sequence` it
|
|
@@ -962,7 +964,7 @@ var FAILURE_COPY = {
|
|
|
962
964
|
/** The question a link-only channel lands on, answered by a POST form. */
|
|
963
965
|
function confirmPage(url, grant) {
|
|
964
966
|
const action = `${url.pathname}?exp=${encodeURIComponent(url.searchParams.get("exp") ?? "")}&sig=${encodeURIComponent(url.searchParams.get("sig") ?? "")}&confirm=1`;
|
|
965
|
-
return `<!doctype html><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Confirm</title><style>body{font:16px/1.5 system-ui,sans-serif;margin:0;min-height:100vh;display:grid;place-items:center;background:#111;color:#eee}main{max-width:24rem;padding:2rem;text-align:center}h1{font-size:1.25rem;margin:0 0 1rem}button{font:inherit;padding:.6rem 1.4rem;border-radius:.5rem;border:0;background:#3b82f6;color:#fff}</style><main><h1>Confirm</h1><p>${grant.verdict === "correct" ? "Mark this detection as correct?" : grant.suggestedClass === void 0 ? "Mark this detection as wrong?" : `Mark this detection as wrong, it was a ${grant.suggestedClass}?`}</p><form method="post" action="${action}"><button type="submit">Confirm</button></form></main>`;
|
|
967
|
+
return `<!doctype html><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Confirm</title><style>body{font:16px/1.5 system-ui,sans-serif;margin:0;min-height:100vh;display:grid;place-items:center;background:#111;color:#eee}main{max-width:24rem;padding:2rem;text-align:center}h1{font-size:1.25rem;margin:0 0 1rem}button{font:inherit;padding:.6rem 1.4rem;border-radius:.5rem;border:0;background:#3b82f6;color:#fff}</style><main><h1>Confirm</h1><p>${grant.verdict === "wrong-label" ? "Mark the label of this detection as wrong (the class is right)?" : grant.verdict === "correct" ? "Mark this detection as correct?" : grant.suggestedClass === void 0 ? "Mark this detection as wrong?" : `Mark this detection as wrong, it was a ${grant.suggestedClass}?`}</p><form method="post" action="${action}"><button type="submit">Confirm</button></form></main>`;
|
|
966
968
|
}
|
|
967
969
|
function page(title, detail) {
|
|
968
970
|
return `<!doctype html><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${title}</title><style>body{font:16px/1.5 system-ui,sans-serif;margin:0;min-height:100vh;display:grid;place-items:center;background:#111;color:#eee}main{max-width:24rem;padding:2rem;text-align:center}h1{font-size:1.25rem;margin:0 0 .5rem}p{margin:0;color:#aaa}</style><main><h1>${title}</h1><p>${detail}</p></main>`;
|
|
@@ -2945,7 +2947,6 @@ var NIGHT = "night";
|
|
|
2945
2947
|
var IR = "ir";
|
|
2946
2948
|
var DAWN = "dawn";
|
|
2947
2949
|
var DUSK = "dusk";
|
|
2948
|
-
var DEG = Math.PI / 180;
|
|
2949
2950
|
/**
|
|
2950
2951
|
* Mean channel spread below which a frame is judged infrared.
|
|
2951
2952
|
*
|
|
@@ -2967,38 +2968,6 @@ var IR_CHROMA_THRESHOLD = 6;
|
|
|
2967
2968
|
* scene reports `unknown` — the honest answer.
|
|
2968
2969
|
*/
|
|
2969
2970
|
var TWILIGHT_BAND_MS = 2400 * 1e3;
|
|
2970
|
-
/** Julian day number for a JS Date (UTC). */
|
|
2971
|
-
function toJulian(date) {
|
|
2972
|
-
return date.getTime() / 864e5 + 2440587.5;
|
|
2973
|
-
}
|
|
2974
|
-
/** Julian day → epoch ms (UTC). */
|
|
2975
|
-
function fromJulian(j) {
|
|
2976
|
-
return (j - 2440587.5) * 864e5;
|
|
2977
|
-
}
|
|
2978
|
-
/**
|
|
2979
|
-
* Sunrise/sunset (UTC epoch ms) for a location and date via the standard NOAA
|
|
2980
|
-
* sunrise equation. Returns `null` for the polar edge cases (sun never
|
|
2981
|
-
* rises/sets that day) so the caller can degrade to the clock split.
|
|
2982
|
-
*/
|
|
2983
|
-
function sunTimes(lat, lng, date) {
|
|
2984
|
-
const jDate = toJulian(date);
|
|
2985
|
-
const jStar = Math.round(jDate - 2451545 + 8e-4) - lng / 360;
|
|
2986
|
-
const m = (357.5291 + .98560028 * jStar) % 360;
|
|
2987
|
-
const mRad = m * DEG;
|
|
2988
|
-
const lambda = (m + (1.9148 * Math.sin(mRad) + .02 * Math.sin(2 * mRad) + 3e-4 * Math.sin(3 * mRad)) + 180 + 102.9372) % 360 * DEG;
|
|
2989
|
-
const jTransit = 2451545 + jStar + .0053 * Math.sin(mRad) - .0069 * Math.sin(2 * lambda);
|
|
2990
|
-
const declination = Math.asin(Math.sin(lambda) * Math.sin(23.44 * DEG));
|
|
2991
|
-
const latRad = lat * DEG;
|
|
2992
|
-
const cosOmega = (Math.sin(-.833 * DEG) - Math.sin(latRad) * Math.sin(declination)) / (Math.cos(latRad) * Math.cos(declination));
|
|
2993
|
-
if (cosOmega > 1 || cosOmega < -1) return null;
|
|
2994
|
-
const omega = Math.acos(cosOmega) / DEG;
|
|
2995
|
-
const jRise = jTransit - omega / 360;
|
|
2996
|
-
const jSet = jTransit + omega / 360;
|
|
2997
|
-
return {
|
|
2998
|
-
rise: fromJulian(jRise),
|
|
2999
|
-
set: fromJulian(jSet)
|
|
3000
|
-
};
|
|
3001
|
-
}
|
|
3002
2971
|
/** Coarse UTC clock split — day between 06:00 and 20:00 UTC. Deterministic
|
|
3003
2972
|
* last resort when no coordinates let us compute real sun-times. */
|
|
3004
2973
|
function clockCondition(now) {
|
|
@@ -7366,7 +7335,8 @@ var OPENING = new Set([
|
|
|
7366
7335
|
"open",
|
|
7367
7336
|
"opening",
|
|
7368
7337
|
"unlocked",
|
|
7369
|
-
"unlocking"
|
|
7338
|
+
"unlocking",
|
|
7339
|
+
"door-open"
|
|
7370
7340
|
]);
|
|
7371
7341
|
function sensorEdgeOf(kind, value) {
|
|
7372
7342
|
const opening = alarmOpeningFromSensorEvent(kind, value);
|
|
@@ -9281,6 +9251,7 @@ var en_default = {
|
|
|
9281
9251
|
"button.verdict.correct": "Correct",
|
|
9282
9252
|
"button.verdict.wrong": "Wrong",
|
|
9283
9253
|
"button.verdict.wrongAs": "Wrong: it is {{class}}",
|
|
9254
|
+
"button.verdict.wrongLabel": "Wrong label, class OK",
|
|
9284
9255
|
"action.server-update.title": "Server update",
|
|
9285
9256
|
"action.server-update.started": "Updating server on {{nodeId}}…",
|
|
9286
9257
|
"action.server-update.restarting": "Server update staged on {{nodeId}} — the node is restarting. You will hear when it comes back.",
|
|
@@ -9686,6 +9657,7 @@ var it_default = {
|
|
|
9686
9657
|
"button.verdict.correct": "Corretto",
|
|
9687
9658
|
"button.verdict.wrong": "Sbagliato",
|
|
9688
9659
|
"button.verdict.wrongAs": "Sbagliato: è {{class}}",
|
|
9660
|
+
"button.verdict.wrongLabel": "Etichetta sbagliata, classe giusta",
|
|
9689
9661
|
"action.server-update.title": "Aggiornamento server",
|
|
9690
9662
|
"action.server-update.started": "Aggiornamento server su {{nodeId}}…",
|
|
9691
9663
|
"action.server-update.restarting": "Aggiornamento server predisposto su {{nodeId}} — il nodo si riavvia. Ti avviseremo quando torna.",
|
|
@@ -39035,6 +39007,11 @@ function rowIsDurableRetrainCopy(data) {
|
|
|
39035
39007
|
* audit resolves ownership from INDEX rows, but a future filesystem-side tool
|
|
39036
39008
|
* must be able to tell the two corpora apart by path alone. */
|
|
39037
39009
|
var RETRAIN_PATH_PREFIX = "retrain";
|
|
39010
|
+
/** The stored verdict subject, validated; anything unreadable reads as absent. */
|
|
39011
|
+
function narrowVerdictSubject(value) {
|
|
39012
|
+
const parsed = RetrainVerdictSubjectSchema.safeParse(value);
|
|
39013
|
+
return parsed.success ? { verdictSubject: parsed.data } : {};
|
|
39014
|
+
}
|
|
39038
39015
|
/** Ids per `IN (…)` page in {@link RetrainFrameStore.getMany}. */
|
|
39039
39016
|
var GET_MANY_PAGE = 500;
|
|
39040
39017
|
/**
|
|
@@ -39118,7 +39095,8 @@ var RetrainFrameStore = class {
|
|
|
39118
39095
|
complete: data["complete"] === true || data["complete"] === 1,
|
|
39119
39096
|
...finiteNumber(data["epochMs"]) !== void 0 ? { epochMs: finiteNumber(data["epochMs"]) } : {},
|
|
39120
39097
|
revision: finiteNumber(data["revision"]) ?? 0,
|
|
39121
|
-
dismissed: narrowDismissed(data["dismissed"])
|
|
39098
|
+
dismissed: narrowDismissed(data["dismissed"]),
|
|
39099
|
+
...narrowVerdictSubject(data["verdictSubject"])
|
|
39122
39100
|
};
|
|
39123
39101
|
}
|
|
39124
39102
|
/** The copies with these ids, in the order given; unknown ids are skipped. */
|
|
@@ -39471,7 +39449,8 @@ var RetrainFrameStore = class {
|
|
|
39471
39449
|
capturedAt: input.epochMs,
|
|
39472
39450
|
...chromaSpread !== void 0 ? { chromaSpread } : {},
|
|
39473
39451
|
complete: false,
|
|
39474
|
-
epochMs: input.epochMs
|
|
39452
|
+
epochMs: input.epochMs,
|
|
39453
|
+
...input.verdictSubject !== void 0 ? { verdictSubject: input.verdictSubject } : {}
|
|
39475
39454
|
};
|
|
39476
39455
|
const path = framePath(frame);
|
|
39477
39456
|
const persist = async () => {
|
|
@@ -39495,7 +39474,8 @@ var RetrainFrameStore = class {
|
|
|
39495
39474
|
chromaSpread: frame.chromaSpread ?? null,
|
|
39496
39475
|
complete: false,
|
|
39497
39476
|
origin: "recording",
|
|
39498
|
-
epochMs: input.epochMs
|
|
39477
|
+
epochMs: input.epochMs,
|
|
39478
|
+
...input.verdictSubject !== void 0 ? { verdictSubject: input.verdictSubject } : {}
|
|
39499
39479
|
});
|
|
39500
39480
|
await this.ledger.transact([row, ...withRow]);
|
|
39501
39481
|
};
|
|
@@ -39532,6 +39512,22 @@ var RetrainFrameStore = class {
|
|
|
39532
39512
|
};
|
|
39533
39513
|
}
|
|
39534
39514
|
/**
|
|
39515
|
+
* Record the verdict subject on a still that already existed (the moment was
|
|
39516
|
+
* in the dataset before the operator tapped). The latest answer wins, like
|
|
39517
|
+
* the verdict ledger.
|
|
39518
|
+
*
|
|
39519
|
+
* @returns the updated frame, or `null` when no such copy exists.
|
|
39520
|
+
*/
|
|
39521
|
+
async setVerdictSubject(frameId, verdictSubject) {
|
|
39522
|
+
const existing = await this.get(frameId);
|
|
39523
|
+
if (existing === null) return null;
|
|
39524
|
+
await this.ledger.update(frameId, { verdictSubject });
|
|
39525
|
+
return {
|
|
39526
|
+
...existing,
|
|
39527
|
+
verdictSubject
|
|
39528
|
+
};
|
|
39529
|
+
}
|
|
39530
|
+
/**
|
|
39535
39531
|
* The operator's "every subject in this frame is boxed" (D785 context: an
|
|
39536
39532
|
* unboxed subject is a false positive to a detector evaluation). Only the
|
|
39537
39533
|
* operator sets it; nothing derives it from the annotation count, because a
|
|
@@ -68420,6 +68416,7 @@ function wireSubscriptions(deps) {
|
|
|
68420
68416
|
deps.onClusterTopology(nodes);
|
|
68421
68417
|
}));
|
|
68422
68418
|
for (const category of NC_SYSTEM_EVENT_CATEGORIES) unsubs.push(deps.eventBus.subscribe({ category }, (ev) => deps.onSystemEvent(ev)));
|
|
68419
|
+
for (const category of ACTION_TARGET_INVALIDATION_EVENTS) unsubs.push(deps.eventBus.subscribe({ category }, () => deps.onDeviceRegistryChange()));
|
|
68423
68420
|
}
|
|
68424
68421
|
unsubs.push(deps.eventBus.subscribe({ category: EventCategory.DeviceBindingsChanged }, (ev) => {
|
|
68425
68422
|
deps.onBindingsChanged(ev.data);
|
|
@@ -68981,6 +68978,12 @@ async function composeEventKindsForDevices(deviceIds, composeOne, onError) {
|
|
|
68981
68978
|
* nearest one is normally the same detection; the delta is reported so a
|
|
68982
68979
|
* reviewer can see how far it was.
|
|
68983
68980
|
*
|
|
68981
|
+
* 0. **The subject a notification verdict froze** (a recording still landed by
|
|
68982
|
+
* a verdict whose track was already gone). It is the one subject the
|
|
68983
|
+
* operator answered about, so it comes FIRST and is the own box; the
|
|
68984
|
+
* neighbours below stay secondary. Its box is normalised against the full
|
|
68985
|
+
* frame already, so it is used as is — never re-scaled.
|
|
68986
|
+
*
|
|
68984
68987
|
* Every OTHER track alive on the camera at that instant contributes its own
|
|
68985
68988
|
* nearest position the same way — a frame with three people is three boxes,
|
|
68986
68989
|
* and a recording still (no track of its own) gets everything the pipeline
|
|
@@ -69035,6 +69038,18 @@ function toRetrainClassTiers(className, label) {
|
|
|
69035
69038
|
label: kept
|
|
69036
69039
|
} : { macroClass };
|
|
69037
69040
|
}
|
|
69041
|
+
/** A verdict on the wire: the operator's class split into tiers once, here. */
|
|
69042
|
+
function toRetrainVerdict(input) {
|
|
69043
|
+
const tiers = input.suggestedClass !== void 0 ? toRetrainClassTiers(input.suggestedClass, void 0) : null;
|
|
69044
|
+
return {
|
|
69045
|
+
verdict: input.verdict,
|
|
69046
|
+
trackId: input.trackId,
|
|
69047
|
+
...input.suggestedClass !== void 0 ? { suggestedClass: input.suggestedClass } : {},
|
|
69048
|
+
...tiers !== null ? { suggestedMacroClass: tiers.macroClass } : {},
|
|
69049
|
+
...tiers?.label !== void 0 ? { suggestedLabel: tiers.label } : {},
|
|
69050
|
+
...input.at !== void 0 ? { at: input.at } : {}
|
|
69051
|
+
};
|
|
69052
|
+
}
|
|
69038
69053
|
/** A pixel box as a clamped normalised one, or `null` when nothing is left. */
|
|
69039
69054
|
function normalise(box, frameWidth, frameHeight) {
|
|
69040
69055
|
if (frameWidth === void 0 || frameHeight === void 0) return null;
|
|
@@ -69092,6 +69107,22 @@ function boxFor(track, bbox, basis, deltaMs, score) {
|
|
|
69092
69107
|
deltaMs
|
|
69093
69108
|
};
|
|
69094
69109
|
}
|
|
69110
|
+
/** The box a notification verdict froze, or `null` when the event carried none. */
|
|
69111
|
+
function boxOfVerdict(subject) {
|
|
69112
|
+
const box = subject.bbox;
|
|
69113
|
+
if (box === void 0) return null;
|
|
69114
|
+
const clamped = normalise(box, 1, 1);
|
|
69115
|
+
if (clamped === null) return null;
|
|
69116
|
+
const tiers = toRetrainClassTiers(subject.className, subject.label);
|
|
69117
|
+
return {
|
|
69118
|
+
bbox: clamped,
|
|
69119
|
+
macroClass: tiers.macroClass,
|
|
69120
|
+
...tiers.label !== void 0 ? { label: tiers.label } : {},
|
|
69121
|
+
trackId: subject.trackId,
|
|
69122
|
+
basis: "verdict",
|
|
69123
|
+
deltaMs: 0
|
|
69124
|
+
};
|
|
69125
|
+
}
|
|
69095
69126
|
/** The own track's box: the recorded subject box first, the nearest position second. */
|
|
69096
69127
|
function ownBox(input, tolerance) {
|
|
69097
69128
|
const track = input.ownTrack;
|
|
@@ -69114,10 +69145,13 @@ function pipelineBoxesForFrame(input) {
|
|
|
69114
69145
|
const out = [];
|
|
69115
69146
|
const own = ownBox(input, tolerance);
|
|
69116
69147
|
if (own !== null) out.push(own);
|
|
69148
|
+
const verdictBox = input.verdictSubject !== void 0 ? boxOfVerdict(input.verdictSubject) : null;
|
|
69149
|
+
if (verdictBox !== null) out.push(verdictBox);
|
|
69117
69150
|
const at = input.frame.capturedAt;
|
|
69118
69151
|
if (at === void 0) return out;
|
|
69119
69152
|
const ownId = input.frame.trackId;
|
|
69120
69153
|
const seen = new Set(ownId !== void 0 ? [ownId] : []);
|
|
69154
|
+
if (input.verdictSubject !== void 0) seen.add(input.verdictSubject.trackId);
|
|
69121
69155
|
for (const track of input.neighbours) {
|
|
69122
69156
|
if (seen.has(track.trackId) || track.deviceId !== input.frame.deviceId) continue;
|
|
69123
69157
|
seen.add(track.trackId);
|
|
@@ -70439,6 +70473,23 @@ Object.freeze({
|
|
|
70439
70473
|
"sendMediaCommand": { "repeat": 1 },
|
|
70440
70474
|
"setConfig": { "config": { "__nested__": { "defaultTransmitterId": null } } }
|
|
70441
70475
|
},
|
|
70476
|
+
"schedulers": {
|
|
70477
|
+
"conflicts": { "scheduler": { "__nested__": {
|
|
70478
|
+
"enabled": true,
|
|
70479
|
+
"priority": 0,
|
|
70480
|
+
"maxLateMs": 6e5
|
|
70481
|
+
} } },
|
|
70482
|
+
"create": { "scheduler": { "__nested__": {
|
|
70483
|
+
"enabled": true,
|
|
70484
|
+
"priority": 0,
|
|
70485
|
+
"maxLateMs": 6e5
|
|
70486
|
+
} } },
|
|
70487
|
+
"update": { "scheduler": { "__nested__": {
|
|
70488
|
+
"enabled": true,
|
|
70489
|
+
"priority": 0,
|
|
70490
|
+
"maxLateMs": 6e5
|
|
70491
|
+
} } }
|
|
70492
|
+
},
|
|
70442
70493
|
"storage": { "upsertLocation": { "isSystem": false } },
|
|
70443
70494
|
"storage-admin": { "readRecords": { "limit": 100 } },
|
|
70444
70495
|
"storage-provider": {
|
|
@@ -82367,10 +82418,18 @@ function parseActions(raw) {
|
|
|
82367
82418
|
for (const entry of raw) {
|
|
82368
82419
|
const parsed = NcRuleActionSchema.safeParse(entry);
|
|
82369
82420
|
if (!parsed.success) return null;
|
|
82370
|
-
out.push(parsed.data);
|
|
82421
|
+
out.push(normalizeNcAction(parsed.data));
|
|
82371
82422
|
}
|
|
82372
82423
|
return out;
|
|
82373
82424
|
}
|
|
82425
|
+
/** Does a stored row still carry a pre-D983 cap step (`deviceId`, no `target`)? */
|
|
82426
|
+
function hasLegacyTarget(raw) {
|
|
82427
|
+
if (!Array.isArray(raw)) return false;
|
|
82428
|
+
return raw.some((entry) => {
|
|
82429
|
+
const parsed = NcRuleActionSchema.safeParse(entry);
|
|
82430
|
+
return parsed.success && parsed.data.kind === "cap" && parsed.data.target === void 0;
|
|
82431
|
+
});
|
|
82432
|
+
}
|
|
82374
82433
|
function rowToSequence(id, body) {
|
|
82375
82434
|
const actions = parseActions(body.actions);
|
|
82376
82435
|
if (actions === null) return null;
|
|
@@ -82409,6 +82468,7 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82409
82468
|
try {
|
|
82410
82469
|
const { records } = await this.kind.query({ limit: 1e4 });
|
|
82411
82470
|
const next = /* @__PURE__ */ new Map();
|
|
82471
|
+
const legacyRows = [];
|
|
82412
82472
|
let skipped = 0;
|
|
82413
82473
|
for (const row of records) {
|
|
82414
82474
|
const sequence = rowToSequence(row.id, row.data);
|
|
@@ -82417,9 +82477,11 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82417
82477
|
continue;
|
|
82418
82478
|
}
|
|
82419
82479
|
next.set(sequence.id, sequence);
|
|
82480
|
+
if (hasLegacyTarget(row.data.actions)) legacyRows.push(row.id);
|
|
82420
82481
|
}
|
|
82421
82482
|
this.byId.clear();
|
|
82422
82483
|
for (const [id, seq] of next) this.byId.set(id, seq);
|
|
82484
|
+
await this.rewriteLegacyRows(legacyRows, records);
|
|
82423
82485
|
if (skipped > 0) this.logger.warn("sequence rows skipped as malformed — bindings to them will miss", { meta: { skipped } });
|
|
82424
82486
|
} catch (err) {
|
|
82425
82487
|
this.logger.warn("sequence load failed — keeping the sequences already in memory", { meta: {
|
|
@@ -82428,6 +82490,28 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82428
82490
|
} });
|
|
82429
82491
|
}
|
|
82430
82492
|
}
|
|
82493
|
+
/**
|
|
82494
|
+
* One-shot, idempotent (D983): a row whose steps still carry `deviceId` is
|
|
82495
|
+
* stored again in the target shape. A failed write leaves the row as it was —
|
|
82496
|
+
* it is still READ as the new shape — and is on the record.
|
|
82497
|
+
*/
|
|
82498
|
+
async rewriteLegacyRows(ids, records) {
|
|
82499
|
+
for (const id of ids) {
|
|
82500
|
+
const sequence = this.byId.get(id) ?? null;
|
|
82501
|
+
const row = records.find((r) => r.id === id);
|
|
82502
|
+
if (sequence === null || row === void 0) continue;
|
|
82503
|
+
try {
|
|
82504
|
+
const createdAt = row.data.createdAt;
|
|
82505
|
+
await this.persist(sequence, typeof createdAt === "number" && Number.isFinite(createdAt) ? createdAt : this.now(), this.now());
|
|
82506
|
+
this.logger.info("notification sequence rewritten to the target shape", { meta: { sequenceId: id } });
|
|
82507
|
+
} catch (err) {
|
|
82508
|
+
this.logger.warn("notification sequence could not be rewritten — it is still read as the target shape", { meta: {
|
|
82509
|
+
sequenceId: id,
|
|
82510
|
+
error: String(err)
|
|
82511
|
+
} });
|
|
82512
|
+
}
|
|
82513
|
+
}
|
|
82514
|
+
}
|
|
82431
82515
|
list() {
|
|
82432
82516
|
return [...this.byId.values()].toSorted((a, b) => a.name.localeCompare(b.name));
|
|
82433
82517
|
}
|
|
@@ -82447,7 +82531,7 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82447
82531
|
id: randomUUID(),
|
|
82448
82532
|
name: input.name,
|
|
82449
82533
|
...input.minDelaySec !== void 0 ? { minDelaySec: input.minDelaySec } : {},
|
|
82450
|
-
actions:
|
|
82534
|
+
actions: input.actions.map(normalizeNcAction)
|
|
82451
82535
|
};
|
|
82452
82536
|
await this.persist(sequence, now, now);
|
|
82453
82537
|
this.byId.set(sequence.id, sequence);
|
|
@@ -82463,7 +82547,7 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82463
82547
|
id: sequence.id,
|
|
82464
82548
|
name: sequence.name,
|
|
82465
82549
|
...sequence.minDelaySec !== void 0 ? { minDelaySec: sequence.minDelaySec } : {},
|
|
82466
|
-
actions:
|
|
82550
|
+
actions: sequence.actions.map(normalizeNcAction)
|
|
82467
82551
|
};
|
|
82468
82552
|
await this.persist(stored, now, now);
|
|
82469
82553
|
this.byId.set(stored.id, stored);
|
|
@@ -82476,7 +82560,7 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82476
82560
|
id: sequenceId,
|
|
82477
82561
|
name: input.name,
|
|
82478
82562
|
...input.minDelaySec !== void 0 ? { minDelaySec: input.minDelaySec } : {},
|
|
82479
|
-
actions:
|
|
82563
|
+
actions: input.actions.map(normalizeNcAction)
|
|
82480
82564
|
};
|
|
82481
82565
|
const createdAt = await this.readCreatedAt(sequenceId, now);
|
|
82482
82566
|
await this.persist(sequence, createdAt, now);
|
|
@@ -82544,7 +82628,11 @@ var NC_DETECTION_VERDICTS_COLUMNS = [
|
|
|
82544
82628
|
var NcDetectionVerdictRecordSchema = object({
|
|
82545
82629
|
trackId: string().min(1),
|
|
82546
82630
|
deviceId: number().int(),
|
|
82547
|
-
verdict: _enum([
|
|
82631
|
+
verdict: _enum([
|
|
82632
|
+
"correct",
|
|
82633
|
+
"wrong",
|
|
82634
|
+
"wrong-label"
|
|
82635
|
+
]),
|
|
82548
82636
|
/** The class the operator said it really was. Only with `wrong`. */
|
|
82549
82637
|
suggestedClass: string().min(1).optional(),
|
|
82550
82638
|
/** Whose notification it was (the token's frozen owner), NOT who tapped. */
|
|
@@ -82579,6 +82667,16 @@ var NcDetectionVerdictLedger = class {
|
|
|
82579
82667
|
logger: deps.logger
|
|
82580
82668
|
});
|
|
82581
82669
|
}
|
|
82670
|
+
/** The answers recorded for these tracks (a track nobody answered is absent).
|
|
82671
|
+
* Reads the in-memory mirror: no I/O, so a listing never waits on it. */
|
|
82672
|
+
forTracks(trackIds) {
|
|
82673
|
+
const out = /* @__PURE__ */ new Map();
|
|
82674
|
+
for (const id of trackIds) {
|
|
82675
|
+
const row = this.ledger.get(id);
|
|
82676
|
+
if (row !== void 0) out.set(id, row);
|
|
82677
|
+
}
|
|
82678
|
+
return out;
|
|
82679
|
+
}
|
|
82582
82680
|
/** Write-through; throws on a failed write so the tap reports it. */
|
|
82583
82681
|
async record(row) {
|
|
82584
82682
|
await this.ledger.put(NcDetectionVerdictRecordSchema.parse(row));
|
|
@@ -82712,10 +82810,33 @@ function pruneHookBindings(bindings, field, isDead, notes) {
|
|
|
82712
82810
|
kept.push(binding);
|
|
82713
82811
|
continue;
|
|
82714
82812
|
}
|
|
82715
|
-
if (binding.action.kind === "cap"
|
|
82716
|
-
|
|
82717
|
-
|
|
82718
|
-
|
|
82813
|
+
if (binding.action.kind === "cap") {
|
|
82814
|
+
const { target } = normalizeNcCapTarget(binding.action);
|
|
82815
|
+
if (target.kind === "devices") {
|
|
82816
|
+
const dead = target.ids.filter(isDead);
|
|
82817
|
+
if (dead.length === target.ids.length) {
|
|
82818
|
+
changed = true;
|
|
82819
|
+
notes.removed(field, deviceSubjects(dead), "binding-removed");
|
|
82820
|
+
continue;
|
|
82821
|
+
}
|
|
82822
|
+
if (dead.length > 0) {
|
|
82823
|
+
changed = true;
|
|
82824
|
+
notes.removed(field, deviceSubjects(dead), "binding-removed");
|
|
82825
|
+
const alive = target.ids.filter((id) => !isDead(id));
|
|
82826
|
+
kept.push({
|
|
82827
|
+
...binding,
|
|
82828
|
+
action: normalizeNcAction({
|
|
82829
|
+
...binding.action,
|
|
82830
|
+
deviceId: void 0,
|
|
82831
|
+
target: {
|
|
82832
|
+
kind: "devices",
|
|
82833
|
+
ids: alive
|
|
82834
|
+
}
|
|
82835
|
+
})
|
|
82836
|
+
});
|
|
82837
|
+
continue;
|
|
82838
|
+
}
|
|
82839
|
+
}
|
|
82719
82840
|
}
|
|
82720
82841
|
kept.push(binding);
|
|
82721
82842
|
}
|
|
@@ -82871,7 +82992,11 @@ function referencedDeviceIds(snapshot) {
|
|
|
82871
82992
|
add(c.systemEvent?.deviceIds);
|
|
82872
82993
|
if (c.deviceState !== void 0) ids.add(c.deviceState.deviceId);
|
|
82873
82994
|
if (c.scene?.deviceId !== void 0) ids.add(c.scene.deviceId);
|
|
82874
|
-
for (const binding of [...rule.actions?.onTrigger ?? [], ...rule.actions?.onTriggerOff ?? []])
|
|
82995
|
+
for (const binding of [...rule.actions?.onTrigger ?? [], ...rule.actions?.onTriggerOff ?? []]) {
|
|
82996
|
+
if (binding.kind !== "do" || binding.action.kind !== "cap") continue;
|
|
82997
|
+
const { target } = normalizeNcCapTarget(binding.action);
|
|
82998
|
+
if (target.kind === "devices") add(target.ids);
|
|
82999
|
+
}
|
|
82875
83000
|
}
|
|
82876
83001
|
for (const rule of snapshot.timelapse) add(rule.deviceIds);
|
|
82877
83002
|
for (const rule of snapshot.summary) add(rule.deviceIds);
|
|
@@ -83542,6 +83667,8 @@ var NcDeviceStateCache = class {
|
|
|
83542
83667
|
//#region src/notification-center/detection-verdict-buttons.ts
|
|
83543
83668
|
var VERDICT_CORRECT_ID = "detection-verdict-correct";
|
|
83544
83669
|
var VERDICT_WRONG_ID = "detection-verdict-wrong";
|
|
83670
|
+
/** Wrong LABEL, right class — only for a subject that has a label. */
|
|
83671
|
+
var VERDICT_WRONG_LABEL_ID = "detection-verdict-wrong-label";
|
|
83545
83672
|
/** `detection-verdict-wrong:<class>` — Wrong, and what it really was. */
|
|
83546
83673
|
var VERDICT_WRONG_AS_PREFIX = "detection-verdict-wrong:";
|
|
83547
83674
|
/** The macro classes offered as "it was really…". Short on purpose. */
|
|
@@ -83558,6 +83685,15 @@ function verdictButtonRefusal(subject) {
|
|
|
83558
83685
|
if (subject.ownerUserId === void 0) return "unowned-target";
|
|
83559
83686
|
return null;
|
|
83560
83687
|
}
|
|
83688
|
+
/**
|
|
83689
|
+
* Does the notified subject carry a label below its macro class — a sub-class
|
|
83690
|
+
* (`dog` under `animal`), a recognised name, a plate? The same tier split the
|
|
83691
|
+
* retrain annotations use, so "has a label" means one thing in both places.
|
|
83692
|
+
*/
|
|
83693
|
+
function subjectHasLabel(className, label) {
|
|
83694
|
+
if (className === void 0) return false;
|
|
83695
|
+
return toRetrainClassTiers(className, label).label !== void 0;
|
|
83696
|
+
}
|
|
83561
83697
|
/** The classes worth offering for a subject of `className`. */
|
|
83562
83698
|
function verdictClassChoices(className) {
|
|
83563
83699
|
return VERDICT_CLASS_CHOICES.filter((c) => c !== className).slice(0, VERDICT_MAX_CLASS_CHOICES);
|
|
@@ -83569,13 +83705,17 @@ function verdictClassChoices(className) {
|
|
|
83569
83705
|
* when the channel declared room for a fourth button.
|
|
83570
83706
|
*/
|
|
83571
83707
|
function verdictButtonSpecs(input) {
|
|
83572
|
-
const
|
|
83708
|
+
const plain = [{
|
|
83573
83709
|
actionId: VERDICT_CORRECT_ID,
|
|
83574
83710
|
verdict: "correct"
|
|
83575
83711
|
}, {
|
|
83576
83712
|
actionId: VERDICT_WRONG_ID,
|
|
83577
83713
|
verdict: "wrong"
|
|
83578
83714
|
}];
|
|
83715
|
+
const base = subjectHasLabel(input.className, input.label) ? [...plain, {
|
|
83716
|
+
actionId: VERDICT_WRONG_LABEL_ID,
|
|
83717
|
+
verdict: "wrong-label"
|
|
83718
|
+
}] : plain;
|
|
83579
83719
|
if (input.maxActions === void 0 || input.maxActions <= 3) return base;
|
|
83580
83720
|
const room = input.maxActions - base.length;
|
|
83581
83721
|
const extra = verdictClassChoices(input.className).slice(0, room).map((suggestedClass) => ({
|
|
@@ -87306,6 +87446,8 @@ var NcDispatcher = class {
|
|
|
87306
87446
|
...target.ownerUserId !== void 0 ? { ownerUserId: target.ownerUserId } : {},
|
|
87307
87447
|
...entry.payload.subject.className !== void 0 ? { className: entry.payload.subject.className } : {},
|
|
87308
87448
|
...entry.payload.subject.trackId !== void 0 ? { trackId: entry.payload.subject.trackId } : {},
|
|
87449
|
+
...entry.payload.subject.label !== void 0 ? { label: entry.payload.subject.label } : {},
|
|
87450
|
+
...entry.payload.subject.bbox !== void 0 ? { bbox: entry.payload.subject.bbox } : {},
|
|
87309
87451
|
eventAtMs: entry.payload.subject.timestamp,
|
|
87310
87452
|
...target.maxActions !== void 0 ? { maxActions: target.maxActions } : {},
|
|
87311
87453
|
...entry.payload.subject.systemEvent !== void 0 ? { systemEvent: entry.payload.subject.systemEvent } : {}
|
|
@@ -91669,7 +91811,7 @@ var NcRuleActionRunner = class {
|
|
|
91669
91811
|
if (sequence.throttle) this.lastRunAt.set(sequence.id, now);
|
|
91670
91812
|
let stepsRun = 0;
|
|
91671
91813
|
for (const [index, action] of sequence.actions.entries()) try {
|
|
91672
|
-
await this.step(action, input.origin);
|
|
91814
|
+
await this.step(action, input.origin, sequence.id);
|
|
91673
91815
|
stepsRun += 1;
|
|
91674
91816
|
} catch (err) {
|
|
91675
91817
|
this.deps.logger.warn("rule action failed — stopping the sequence", {
|
|
@@ -91709,20 +91851,28 @@ var NcRuleActionRunner = class {
|
|
|
91709
91851
|
stepsRun
|
|
91710
91852
|
};
|
|
91711
91853
|
}
|
|
91712
|
-
async step(action, origin) {
|
|
91854
|
+
async step(action, origin, owner) {
|
|
91713
91855
|
if (action.kind === "wait") {
|
|
91714
91856
|
await this.sleep(action.seconds * 1e3);
|
|
91715
91857
|
return;
|
|
91716
91858
|
}
|
|
91717
91859
|
if (!this.deps.isDeviceScoped(action.cap)) throw new Error(`rule action refused: "${action.cap}" is not a device capability — only devices can be actuated`);
|
|
91718
|
-
|
|
91719
|
-
|
|
91860
|
+
const { target, actionId } = normalizeNcCapTarget(action);
|
|
91861
|
+
const deviceIds = await this.devicesOf(target, actionId, owner);
|
|
91862
|
+
for (const deviceId of deviceIds) await this.deps.actuate({
|
|
91863
|
+
deviceId,
|
|
91720
91864
|
cap: action.cap,
|
|
91721
91865
|
method: action.method,
|
|
91722
91866
|
args: action.args ?? {},
|
|
91723
91867
|
...origin !== void 0 ? { origin } : {}
|
|
91724
91868
|
});
|
|
91725
91869
|
}
|
|
91870
|
+
async devicesOf(target, actionId, owner) {
|
|
91871
|
+
if (target.kind === "devices") return target.ids;
|
|
91872
|
+
if (target.kind === "var") throw new Error("rule action refused: a sequence has no variables to resolve a target from");
|
|
91873
|
+
if (this.deps.resolveTarget === void 0) throw new Error("rule action refused: this node cannot resolve a domain target");
|
|
91874
|
+
return (await this.deps.resolveTarget(target, actionId, owner)).deviceIds;
|
|
91875
|
+
}
|
|
91726
91876
|
};
|
|
91727
91877
|
/** Force-enable a shared sequence for a button tap (always runs, still throttled). */
|
|
91728
91878
|
function asForcedSequence(sequence) {
|
|
@@ -100110,6 +100260,12 @@ function rowRefusalId(systemEvent) {
|
|
|
100110
100260
|
const value = systemEvent?.data["refusalId"];
|
|
100111
100261
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
100112
100262
|
}
|
|
100263
|
+
/** The text-catalog key of each verdict button. */
|
|
100264
|
+
var VERDICT_LABEL_KEY = {
|
|
100265
|
+
correct: "button.verdict.correct",
|
|
100266
|
+
wrong: "button.verdict.wrong",
|
|
100267
|
+
"wrong-label": "button.verdict.wrongLabel"
|
|
100268
|
+
};
|
|
100113
100269
|
/**
|
|
100114
100270
|
* The tap-through buttons for ONE delivery, each with its own single-use
|
|
100115
100271
|
* token.
|
|
@@ -100146,6 +100302,7 @@ async function mintButtons(host, input) {
|
|
|
100146
100302
|
const verdictOwner = input.ownerUserId;
|
|
100147
100303
|
const verdictButtons = verdictRefusal !== null || verdictTrackId === void 0 || verdictOwner === void 0 ? [] : verdictButtonSpecs({
|
|
100148
100304
|
className: input.className,
|
|
100305
|
+
label: input.label,
|
|
100149
100306
|
maxActions: input.maxActions
|
|
100150
100307
|
}).map((spec) => {
|
|
100151
100308
|
const id = randomUUID();
|
|
@@ -100163,6 +100320,11 @@ async function mintButtons(host, input) {
|
|
|
100163
100320
|
...spec.suggestedClass !== void 0 ? { suggestedClass: spec.suggestedClass } : {},
|
|
100164
100321
|
...input.maxActions === 0 ? { viaLink: true } : {},
|
|
100165
100322
|
...input.eventAtMs !== void 0 ? { eventAtMs: input.eventAtMs } : {},
|
|
100323
|
+
...input.className !== void 0 ? { subject: {
|
|
100324
|
+
className: input.className,
|
|
100325
|
+
...input.label !== void 0 ? { label: input.label } : {},
|
|
100326
|
+
...input.bbox !== void 0 ? { bbox: input.bbox } : {}
|
|
100327
|
+
} } : {},
|
|
100166
100328
|
deviceId: input.deviceId,
|
|
100167
100329
|
actionId: spec.actionId,
|
|
100168
100330
|
targetId: input.targetId,
|
|
@@ -100171,7 +100333,7 @@ async function mintButtons(host, input) {
|
|
|
100171
100333
|
});
|
|
100172
100334
|
return {
|
|
100173
100335
|
id: spec.actionId,
|
|
100174
|
-
label: spec.suggestedClass === void 0 ? host.texts.text({ key: spec.verdict
|
|
100336
|
+
label: spec.suggestedClass === void 0 ? host.texts.text({ key: VERDICT_LABEL_KEY[spec.verdict] }) : host.texts.text({
|
|
100175
100337
|
key: "button.verdict.wrongAs",
|
|
100176
100338
|
vars: { class: spec.suggestedClass }
|
|
100177
100339
|
}),
|
|
@@ -100630,6 +100792,18 @@ var VERDICT_FRAME_REFUSAL_COPY = {
|
|
|
100630
100792
|
"still-busy": "The track is gone and the recorder is busy — nothing was changed, try again later",
|
|
100631
100793
|
failed: "The track is gone and its frame could not be saved — nothing was changed"
|
|
100632
100794
|
};
|
|
100795
|
+
/** The grant's frozen subject, in the shape the retrain still stores it in. */
|
|
100796
|
+
function verdictSubjectOf(grant, subject, at) {
|
|
100797
|
+
return {
|
|
100798
|
+
trackId: grant.trackId,
|
|
100799
|
+
className: subject.className,
|
|
100800
|
+
...subject.label !== void 0 ? { label: subject.label } : {},
|
|
100801
|
+
...subject.bbox !== void 0 ? { bbox: subject.bbox } : {},
|
|
100802
|
+
verdict: grant.verdict,
|
|
100803
|
+
...grant.suggestedClass !== void 0 ? { suggestedClass: grant.suggestedClass } : {},
|
|
100804
|
+
at
|
|
100805
|
+
};
|
|
100806
|
+
}
|
|
100633
100807
|
/**
|
|
100634
100808
|
* The track is gone (aged out, or discarded as a still object): the camera's
|
|
100635
100809
|
* RECORDING still covers the instant, so the verdict lands a frame there
|
|
@@ -100652,7 +100826,8 @@ async function landFrameFromRecording(host, grant) {
|
|
|
100652
100826
|
}
|
|
100653
100827
|
const landed = await addFrame({
|
|
100654
100828
|
deviceId: grant.deviceId,
|
|
100655
|
-
epochMs: grant.eventAtMs
|
|
100829
|
+
epochMs: grant.eventAtMs,
|
|
100830
|
+
...grant.subject !== void 0 ? { subject: verdictSubjectOf(grant, grant.subject, host.now()) } : {}
|
|
100656
100831
|
});
|
|
100657
100832
|
if (!landed.ok) {
|
|
100658
100833
|
host.logger.warn("detection verdict dropped — the track is gone and the recording refused", {
|
|
@@ -101613,6 +101788,7 @@ function buildEntries(host, rule, subject, kind, matchedOn, userTargets = [], or
|
|
|
101613
101788
|
...alarmSource?.eventId !== void 0 ? { eventId: alarmSource.eventId } : hasEventMedia ? { eventId: subject.recordId } : {},
|
|
101614
101789
|
className: subject.classNames[0] ?? subject.sensorKind ?? "event",
|
|
101615
101790
|
...subject.label !== void 0 ? { label: subject.label } : {},
|
|
101791
|
+
...subject.bbox !== void 0 ? { bbox: subject.bbox } : {},
|
|
101616
101792
|
...subject.labelKind !== void 0 ? { labelKind: subject.labelKind } : {},
|
|
101617
101793
|
...subject.confidence !== void 0 ? { confidence: subject.confidence } : {},
|
|
101618
101794
|
zones: renderedZones,
|
|
@@ -105933,6 +106109,8 @@ var NotificationCenter = class {
|
|
|
105933
106109
|
zoneOwners;
|
|
105934
106110
|
/** Runs a matched rule's action sequences. Null when no actuator is wired. */
|
|
105935
106111
|
actionRunner;
|
|
106112
|
+
/** Domain action targets read from the registry (D983); null without a directory. */
|
|
106113
|
+
actionTargets;
|
|
105936
106114
|
/** Grants behind the tap-through buttons. In-process and single-use — read
|
|
105937
106115
|
* `action-token.ts` before assuming anything about what a tap proves. */
|
|
105938
106116
|
actionTokens = new NcActionTokenRegistry();
|
|
@@ -106340,9 +106518,15 @@ var NotificationCenter = class {
|
|
|
106340
106518
|
});
|
|
106341
106519
|
this.livenessHoldoff = new DeviceLivenessHoldoff((event) => this.consumeEvent(event), { delayMs: deps.livenessHoldoffMs ?? (process.env.VITEST ? 0 : DEVICE_LIVENESS_HOLDOFF_MS) });
|
|
106342
106520
|
this.nodeLivenessHoldoff = new DeviceLivenessHoldoff((event, timing) => this.consumeNodeLiveness(event, timing), { delayMs: deps.nodeLivenessHoldoffMs ?? (process.env.VITEST ? 0 : NODE_LIVENESS_HOLDOFF_MS) });
|
|
106521
|
+
const targets = deps.actionTargetDirectory !== void 0 ? new ActionTargetResolver(deps.actionTargetDirectory, this.logger.child("actions")) : null;
|
|
106522
|
+
this.actionTargets = targets;
|
|
106343
106523
|
this.actionRunner = deps.actuate !== void 0 && deps.isCapDeviceScoped !== void 0 ? new NcRuleActionRunner({
|
|
106344
106524
|
logger: this.logger.child("actions"),
|
|
106345
106525
|
actuate: (input) => this.actuateWithAttribution(input),
|
|
106526
|
+
...targets !== null ? { resolveTarget: (target, actionId, owner) => targets.resolve(target, actionId, {}, {
|
|
106527
|
+
actionId,
|
|
106528
|
+
owner
|
|
106529
|
+
}) } : {},
|
|
106346
106530
|
isDeviceScoped: deps.isCapDeviceScoped,
|
|
106347
106531
|
...deps.now !== void 0 ? { now: deps.now } : {}
|
|
106348
106532
|
}) : null;
|
|
@@ -107132,6 +107316,21 @@ var NotificationCenter = class {
|
|
|
107132
107316
|
}
|
|
107133
107317
|
};
|
|
107134
107318
|
}
|
|
107319
|
+
/**
|
|
107320
|
+
* What the operator answered to the "was this detection right?" buttons, for
|
|
107321
|
+
* the retrain page: by track, the latest answer wins. A track nobody answered
|
|
107322
|
+
* is absent.
|
|
107323
|
+
*/
|
|
107324
|
+
detectionVerdictsOf(trackIds) {
|
|
107325
|
+
const out = /* @__PURE__ */ new Map();
|
|
107326
|
+
for (const [trackId, row] of this.verdicts.forTracks(trackIds)) out.set(trackId, toRetrainVerdict({
|
|
107327
|
+
verdict: row.verdict,
|
|
107328
|
+
trackId,
|
|
107329
|
+
at: row.at,
|
|
107330
|
+
suggestedClass: row.suggestedClass
|
|
107331
|
+
}));
|
|
107332
|
+
return out;
|
|
107333
|
+
}
|
|
107135
107334
|
observeOccupancy(deviceId, snapshot, evidence = "scene") {
|
|
107136
107335
|
return observeOccupancy(this.occupancyWatchHost(), deviceId, snapshot, evidence);
|
|
107137
107336
|
}
|
|
@@ -107307,6 +107506,10 @@ var NotificationCenter = class {
|
|
|
107307
107506
|
}
|
|
107308
107507
|
};
|
|
107309
107508
|
}
|
|
107509
|
+
/** The device registry changed: a cached domain action target is stale (D983). */
|
|
107510
|
+
invalidateActionTargets() {
|
|
107511
|
+
this.actionTargets?.invalidate();
|
|
107512
|
+
}
|
|
107310
107513
|
onSystemEvent(event) {
|
|
107311
107514
|
return onSystemEvent(this.systemEventsHost(), event);
|
|
107312
107515
|
}
|
|
@@ -108780,7 +108983,9 @@ async function addVerdictFrameFromRecording(api, logger, input) {
|
|
|
108780
108983
|
}
|
|
108781
108984
|
const result = await api.addRetrainFrameFromRecording({
|
|
108782
108985
|
collectionId,
|
|
108783
|
-
|
|
108986
|
+
deviceId: input.deviceId,
|
|
108987
|
+
epochMs: input.epochMs,
|
|
108988
|
+
...input.subject !== void 0 ? { verdictSubject: input.subject } : {}
|
|
108784
108989
|
});
|
|
108785
108990
|
if (result.kind === "added") return { ok: true };
|
|
108786
108991
|
return {
|
|
@@ -109067,6 +109272,20 @@ var BuildNotificationCenter = class extends BuildNotificationCenterBase {
|
|
|
109067
109272
|
});
|
|
109068
109273
|
},
|
|
109069
109274
|
isCapDeviceScoped: isDeviceScopedCap,
|
|
109275
|
+
actionTargetDirectory: {
|
|
109276
|
+
listDeviceIdsByCaps: (capNames) => api.deviceManager.listDeviceIdsByCaps.query({ capNames: [...capNames] }),
|
|
109277
|
+
listDevices: async (deviceIds) => {
|
|
109278
|
+
return (await api.deviceManager.listAll.query({
|
|
109279
|
+
deviceIds: [...deviceIds],
|
|
109280
|
+
projection: "slim"
|
|
109281
|
+
})).map((d) => ({
|
|
109282
|
+
id: d.id,
|
|
109283
|
+
type: d.type,
|
|
109284
|
+
location: d.location,
|
|
109285
|
+
disabled: d.disabled
|
|
109286
|
+
}));
|
|
109287
|
+
}
|
|
109288
|
+
},
|
|
109070
109289
|
generateVision: async (request) => {
|
|
109071
109290
|
const result = await api.llm.generateVision.mutate({
|
|
109072
109291
|
...request.profileId !== void 0 ? { profileId: request.profileId } : {},
|
|
@@ -113692,7 +113911,7 @@ var RetrainCollectionService = class {
|
|
|
113692
113911
|
frameId: recordingFrameId(input.deviceId, input.epochMs),
|
|
113693
113912
|
deviceId: input.deviceId
|
|
113694
113913
|
});
|
|
113695
|
-
const stored = await this.storeStill(input.deviceId, input.epochMs, membershipOp === null ? [] : [membershipOp]);
|
|
113914
|
+
const stored = await this.storeStill(input.deviceId, input.epochMs, membershipOp === null ? [] : [membershipOp], input.verdictSubject);
|
|
113696
113915
|
if (stored.kind === "refused") {
|
|
113697
113916
|
this.deps.logger.info("retrain collection add refused", {
|
|
113698
113917
|
tags,
|
|
@@ -113704,11 +113923,15 @@ var RetrainCollectionService = class {
|
|
|
113704
113923
|
});
|
|
113705
113924
|
return stored;
|
|
113706
113925
|
}
|
|
113707
|
-
|
|
113708
|
-
|
|
113709
|
-
|
|
113710
|
-
|
|
113711
|
-
|
|
113926
|
+
let storedFrame = stored.frame;
|
|
113927
|
+
if (stored.reused) {
|
|
113928
|
+
await this.deps.collections.addFrame({
|
|
113929
|
+
collectionId: input.collectionId,
|
|
113930
|
+
frameId: stored.frame.frameId,
|
|
113931
|
+
deviceId: input.deviceId
|
|
113932
|
+
});
|
|
113933
|
+
if (input.verdictSubject !== void 0) storedFrame = await this.deps.frames.setVerdictSubject(stored.frame.frameId, input.verdictSubject) ?? stored.frame;
|
|
113934
|
+
}
|
|
113712
113935
|
this.deps.logger.info("retrain frame added to a collection from the recording", {
|
|
113713
113936
|
tags,
|
|
113714
113937
|
meta: {
|
|
@@ -113718,7 +113941,7 @@ var RetrainCollectionService = class {
|
|
|
113718
113941
|
reused: stored.reused
|
|
113719
113942
|
}
|
|
113720
113943
|
});
|
|
113721
|
-
const [wire] = await this.deps.retrain.toWireFrames([
|
|
113944
|
+
const [wire] = await this.deps.retrain.toWireFrames([storedFrame]);
|
|
113722
113945
|
if (wire === void 0) throw new Error("retrain: a stored still produced no wire frame");
|
|
113723
113946
|
return {
|
|
113724
113947
|
kind: "added",
|
|
@@ -113769,7 +113992,7 @@ var RetrainCollectionService = class {
|
|
|
113769
113992
|
const ids = await this.deps.collections.listFrameIds(input.collectionId);
|
|
113770
113993
|
return this.deps.retrain.toWireFrames(await this.deps.frames.getMany(ids));
|
|
113771
113994
|
}
|
|
113772
|
-
async storeStill(deviceId, epochMs, withRow) {
|
|
113995
|
+
async storeStill(deviceId, epochMs, withRow, verdictSubject) {
|
|
113773
113996
|
const existing = await this.deps.frames.get(recordingFrameId(deviceId, epochMs));
|
|
113774
113997
|
if (existing !== null) return {
|
|
113775
113998
|
kind: "stored",
|
|
@@ -113788,7 +114011,8 @@ var RetrainCollectionService = class {
|
|
|
113788
114011
|
const stored = await this.deps.frames.storeRecordingStill({
|
|
113789
114012
|
deviceId,
|
|
113790
114013
|
epochMs,
|
|
113791
|
-
bytes: still.jpeg
|
|
114014
|
+
bytes: still.jpeg,
|
|
114015
|
+
...verdictSubject !== void 0 ? { verdictSubject } : {}
|
|
113792
114016
|
}, withRow);
|
|
113793
114017
|
return stored.kind === "copied" ? {
|
|
113794
114018
|
kind: "stored",
|
|
@@ -114574,6 +114798,14 @@ function toWireFrame(f) {
|
|
|
114574
114798
|
dismissed: f.dismissed ?? []
|
|
114575
114799
|
};
|
|
114576
114800
|
}
|
|
114801
|
+
/** The answer on a frame: a track copy asks the ledger, a still carries the
|
|
114802
|
+
* subject the notification froze. */
|
|
114803
|
+
function verdictOfFrame(copy, verdicts) {
|
|
114804
|
+
if (copy.origin === "track") return verdicts.get(copy.trackId);
|
|
114805
|
+
const s = copy.verdictSubject;
|
|
114806
|
+
if (s === void 0) return void 0;
|
|
114807
|
+
return toRetrainVerdict(s);
|
|
114808
|
+
}
|
|
114577
114809
|
/**
|
|
114578
114810
|
* What the operator did with the proposals on a frame (`retrain-review.ts`).
|
|
114579
114811
|
*
|
|
@@ -114634,7 +114866,11 @@ var RetrainService = class {
|
|
|
114634
114866
|
const tracks = [];
|
|
114635
114867
|
for (const deviceId of devices) tracks.push(...await this.deps.tracks.listStaging(deviceId, limit));
|
|
114636
114868
|
const ids = tracks.map((t) => t.trackId);
|
|
114637
|
-
const [frameCounts, annotationCounts] = await Promise.all([
|
|
114869
|
+
const [frameCounts, annotationCounts, verdicts] = await Promise.all([
|
|
114870
|
+
this.deps.frames.countsByTrack(ids),
|
|
114871
|
+
this.deps.annotations.countsByTrack(ids),
|
|
114872
|
+
this.verdictsOfTracks(ids)
|
|
114873
|
+
]);
|
|
114638
114874
|
return tracks.map((t) => ({
|
|
114639
114875
|
trackId: t.trackId,
|
|
114640
114876
|
deviceId: t.deviceId,
|
|
@@ -114643,7 +114879,8 @@ var RetrainService = class {
|
|
|
114643
114879
|
firstSeen: t.firstSeen,
|
|
114644
114880
|
lastSeen: t.lastSeen,
|
|
114645
114881
|
frameCount: frameCounts.get(t.trackId) ?? 0,
|
|
114646
|
-
annotationCount: annotationCounts.get(t.trackId) ?? 0
|
|
114882
|
+
annotationCount: annotationCounts.get(t.trackId) ?? 0,
|
|
114883
|
+
...verdicts.has(t.trackId) ? { verdict: verdicts.get(t.trackId) } : {}
|
|
114647
114884
|
}));
|
|
114648
114885
|
}
|
|
114649
114886
|
/**
|
|
@@ -114693,9 +114930,14 @@ var RetrainService = class {
|
|
|
114693
114930
|
const ownTracks = /* @__PURE__ */ new Map();
|
|
114694
114931
|
const subjectBoxes = /* @__PURE__ */ new Map();
|
|
114695
114932
|
const annotationsByFrame = await this.annotationsByFrame(copies);
|
|
114933
|
+
const verdicts = await this.verdictsOf(copies);
|
|
114696
114934
|
const out = [];
|
|
114697
114935
|
for (const copy of copies) {
|
|
114698
|
-
const
|
|
114936
|
+
const verdict = verdictOfFrame(copy, verdicts);
|
|
114937
|
+
const wire = {
|
|
114938
|
+
...toWireFrame(copy),
|
|
114939
|
+
...verdict !== void 0 ? { verdict } : {}
|
|
114940
|
+
};
|
|
114699
114941
|
const collectionIds = collections?.get(copy.frameId);
|
|
114700
114942
|
const withCollections = {
|
|
114701
114943
|
...collections !== null ? {
|
|
@@ -114726,7 +114968,8 @@ var RetrainService = class {
|
|
|
114726
114968
|
},
|
|
114727
114969
|
ownTrack: trackId !== "" ? ownTracks.get(trackId) ?? null : null,
|
|
114728
114970
|
ownSubjectBox: trackId !== "" ? subjectBoxes.get(trackId)?.get(copy.sourceMediaId) ?? null : null,
|
|
114729
|
-
neighbours
|
|
114971
|
+
neighbours,
|
|
114972
|
+
...copy.verdictSubject !== void 0 ? { verdictSubject: copy.verdictSubject } : {}
|
|
114730
114973
|
});
|
|
114731
114974
|
out.push({
|
|
114732
114975
|
...withCollections,
|
|
@@ -114736,6 +114979,22 @@ var RetrainService = class {
|
|
|
114736
114979
|
}
|
|
114737
114980
|
return out;
|
|
114738
114981
|
}
|
|
114982
|
+
/** The verdicts of the tracks these frames were copied from. */
|
|
114983
|
+
async verdictsOf(copies) {
|
|
114984
|
+
return this.verdictsOfTracks(copies.flatMap((c) => c.origin === "track" ? [c.trackId] : []));
|
|
114985
|
+
}
|
|
114986
|
+
async verdictsOfTracks(trackIds) {
|
|
114987
|
+
const port = this.deps.verdicts;
|
|
114988
|
+
const ids = [...new Set(trackIds)];
|
|
114989
|
+
if (port === void 0 || ids.length === 0) return /* @__PURE__ */ new Map();
|
|
114990
|
+
return port.forTracks(ids).catch((err) => {
|
|
114991
|
+
this.deps.logger.warn("retrain frames: verdicts unreadable", { meta: {
|
|
114992
|
+
tracks: ids.length,
|
|
114993
|
+
error: String(err)
|
|
114994
|
+
} });
|
|
114995
|
+
return /* @__PURE__ */ new Map();
|
|
114996
|
+
});
|
|
114997
|
+
}
|
|
114739
114998
|
/** The URLs of a frame's pixels, when a data plane is served for them. */
|
|
114740
114999
|
frameUrls(frameId) {
|
|
114741
115000
|
const frameUrl = this.deps.frameUrl;
|
|
@@ -116852,6 +117111,7 @@ var BuildStores = class extends BuildStoresBase {
|
|
|
116852
117111
|
subjectBoxes: (trackId, deviceId) => mediaStore.listSubjectBoxesByOwner("track", trackId, deviceId)
|
|
116853
117112
|
},
|
|
116854
117113
|
memberships: retrainCollectionStore,
|
|
117114
|
+
verdicts: { forTracks: async (trackIds) => this.notificationCenter?.detectionVerdictsOf(trackIds) ?? /* @__PURE__ */ new Map() },
|
|
116855
117115
|
frameUrl: (frameId, size) => retrainFramePath(this.ctx.id, frameId, size)
|
|
116856
117116
|
});
|
|
116857
117117
|
this.retrain = retrain;
|
|
@@ -122563,7 +122823,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
122563
122823
|
onBindingsChanged: (data) => this.handleBindingsChangedEvent(data),
|
|
122564
122824
|
onDeviceUnregistered: (deviceId) => this.handleDeviceUnregisteredEvent(deviceId),
|
|
122565
122825
|
onClusterTopology: (nodes) => this.nodeLiveness.applySnapshot(nodes, Date.now()),
|
|
122566
|
-
onSystemEvent: (event) => this.notificationCenter?.onSystemEvent(event)
|
|
122826
|
+
onSystemEvent: (event) => this.notificationCenter?.onSystemEvent(event),
|
|
122827
|
+
onDeviceRegistryChange: () => this.notificationCenter?.invalidateActionTargets()
|
|
122567
122828
|
});
|
|
122568
122829
|
await step("startTrackingTapes", () => this.startTrackingTapes(this.isPostProcessingNode));
|
|
122569
122830
|
if (this.isPostProcessingNode) await step("startEmbeddingDispatcher", () => this.startEmbeddingDispatcher(logger, transport));
|