@camstack/addon-post-analysis 1.2.654 → 1.2.655
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 +8 -0
- package/dist/{clip-model-registry-CFQBxtE2.js → clip-model-registry-C-en5vSD.js} +68244 -67588
- package/dist/{clip-model-registry-BX6j2lnF.mjs → clip-model-registry-_b3KHYFm.mjs} +68232 -67612
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +1 -1
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Vag6rhEh.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CF-Mts9j.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-C7OJ7wek.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-CnvnZsmk.mjs → hostInit-BSfz5s98.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +315 -72
- package/dist/pipeline-analytics/index.mjs +314 -71
- 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-_b3KHYFm.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) {
|
|
@@ -9281,6 +9250,7 @@ var en_default = {
|
|
|
9281
9250
|
"button.verdict.correct": "Correct",
|
|
9282
9251
|
"button.verdict.wrong": "Wrong",
|
|
9283
9252
|
"button.verdict.wrongAs": "Wrong: it is {{class}}",
|
|
9253
|
+
"button.verdict.wrongLabel": "Wrong label, class OK",
|
|
9284
9254
|
"action.server-update.title": "Server update",
|
|
9285
9255
|
"action.server-update.started": "Updating server on {{nodeId}}…",
|
|
9286
9256
|
"action.server-update.restarting": "Server update staged on {{nodeId}} — the node is restarting. You will hear when it comes back.",
|
|
@@ -9686,6 +9656,7 @@ var it_default = {
|
|
|
9686
9656
|
"button.verdict.correct": "Corretto",
|
|
9687
9657
|
"button.verdict.wrong": "Sbagliato",
|
|
9688
9658
|
"button.verdict.wrongAs": "Sbagliato: è {{class}}",
|
|
9659
|
+
"button.verdict.wrongLabel": "Etichetta sbagliata, classe giusta",
|
|
9689
9660
|
"action.server-update.title": "Aggiornamento server",
|
|
9690
9661
|
"action.server-update.started": "Aggiornamento server su {{nodeId}}…",
|
|
9691
9662
|
"action.server-update.restarting": "Aggiornamento server predisposto su {{nodeId}} — il nodo si riavvia. Ti avviseremo quando torna.",
|
|
@@ -39035,6 +39006,11 @@ function rowIsDurableRetrainCopy(data) {
|
|
|
39035
39006
|
* audit resolves ownership from INDEX rows, but a future filesystem-side tool
|
|
39036
39007
|
* must be able to tell the two corpora apart by path alone. */
|
|
39037
39008
|
var RETRAIN_PATH_PREFIX = "retrain";
|
|
39009
|
+
/** The stored verdict subject, validated; anything unreadable reads as absent. */
|
|
39010
|
+
function narrowVerdictSubject(value) {
|
|
39011
|
+
const parsed = RetrainVerdictSubjectSchema.safeParse(value);
|
|
39012
|
+
return parsed.success ? { verdictSubject: parsed.data } : {};
|
|
39013
|
+
}
|
|
39038
39014
|
/** Ids per `IN (…)` page in {@link RetrainFrameStore.getMany}. */
|
|
39039
39015
|
var GET_MANY_PAGE = 500;
|
|
39040
39016
|
/**
|
|
@@ -39118,7 +39094,8 @@ var RetrainFrameStore = class {
|
|
|
39118
39094
|
complete: data["complete"] === true || data["complete"] === 1,
|
|
39119
39095
|
...finiteNumber(data["epochMs"]) !== void 0 ? { epochMs: finiteNumber(data["epochMs"]) } : {},
|
|
39120
39096
|
revision: finiteNumber(data["revision"]) ?? 0,
|
|
39121
|
-
dismissed: narrowDismissed(data["dismissed"])
|
|
39097
|
+
dismissed: narrowDismissed(data["dismissed"]),
|
|
39098
|
+
...narrowVerdictSubject(data["verdictSubject"])
|
|
39122
39099
|
};
|
|
39123
39100
|
}
|
|
39124
39101
|
/** The copies with these ids, in the order given; unknown ids are skipped. */
|
|
@@ -39471,7 +39448,8 @@ var RetrainFrameStore = class {
|
|
|
39471
39448
|
capturedAt: input.epochMs,
|
|
39472
39449
|
...chromaSpread !== void 0 ? { chromaSpread } : {},
|
|
39473
39450
|
complete: false,
|
|
39474
|
-
epochMs: input.epochMs
|
|
39451
|
+
epochMs: input.epochMs,
|
|
39452
|
+
...input.verdictSubject !== void 0 ? { verdictSubject: input.verdictSubject } : {}
|
|
39475
39453
|
};
|
|
39476
39454
|
const path = framePath(frame);
|
|
39477
39455
|
const persist = async () => {
|
|
@@ -39495,7 +39473,8 @@ var RetrainFrameStore = class {
|
|
|
39495
39473
|
chromaSpread: frame.chromaSpread ?? null,
|
|
39496
39474
|
complete: false,
|
|
39497
39475
|
origin: "recording",
|
|
39498
|
-
epochMs: input.epochMs
|
|
39476
|
+
epochMs: input.epochMs,
|
|
39477
|
+
...input.verdictSubject !== void 0 ? { verdictSubject: input.verdictSubject } : {}
|
|
39499
39478
|
});
|
|
39500
39479
|
await this.ledger.transact([row, ...withRow]);
|
|
39501
39480
|
};
|
|
@@ -39532,6 +39511,22 @@ var RetrainFrameStore = class {
|
|
|
39532
39511
|
};
|
|
39533
39512
|
}
|
|
39534
39513
|
/**
|
|
39514
|
+
* Record the verdict subject on a still that already existed (the moment was
|
|
39515
|
+
* in the dataset before the operator tapped). The latest answer wins, like
|
|
39516
|
+
* the verdict ledger.
|
|
39517
|
+
*
|
|
39518
|
+
* @returns the updated frame, or `null` when no such copy exists.
|
|
39519
|
+
*/
|
|
39520
|
+
async setVerdictSubject(frameId, verdictSubject) {
|
|
39521
|
+
const existing = await this.get(frameId);
|
|
39522
|
+
if (existing === null) return null;
|
|
39523
|
+
await this.ledger.update(frameId, { verdictSubject });
|
|
39524
|
+
return {
|
|
39525
|
+
...existing,
|
|
39526
|
+
verdictSubject
|
|
39527
|
+
};
|
|
39528
|
+
}
|
|
39529
|
+
/**
|
|
39535
39530
|
* The operator's "every subject in this frame is boxed" (D785 context: an
|
|
39536
39531
|
* unboxed subject is a false positive to a detector evaluation). Only the
|
|
39537
39532
|
* operator sets it; nothing derives it from the annotation count, because a
|
|
@@ -68420,6 +68415,7 @@ function wireSubscriptions(deps) {
|
|
|
68420
68415
|
deps.onClusterTopology(nodes);
|
|
68421
68416
|
}));
|
|
68422
68417
|
for (const category of NC_SYSTEM_EVENT_CATEGORIES) unsubs.push(deps.eventBus.subscribe({ category }, (ev) => deps.onSystemEvent(ev)));
|
|
68418
|
+
for (const category of ACTION_TARGET_INVALIDATION_EVENTS) unsubs.push(deps.eventBus.subscribe({ category }, () => deps.onDeviceRegistryChange()));
|
|
68423
68419
|
}
|
|
68424
68420
|
unsubs.push(deps.eventBus.subscribe({ category: EventCategory.DeviceBindingsChanged }, (ev) => {
|
|
68425
68421
|
deps.onBindingsChanged(ev.data);
|
|
@@ -68981,6 +68977,12 @@ async function composeEventKindsForDevices(deviceIds, composeOne, onError) {
|
|
|
68981
68977
|
* nearest one is normally the same detection; the delta is reported so a
|
|
68982
68978
|
* reviewer can see how far it was.
|
|
68983
68979
|
*
|
|
68980
|
+
* 0. **The subject a notification verdict froze** (a recording still landed by
|
|
68981
|
+
* a verdict whose track was already gone). It is the one subject the
|
|
68982
|
+
* operator answered about, so it comes FIRST and is the own box; the
|
|
68983
|
+
* neighbours below stay secondary. Its box is normalised against the full
|
|
68984
|
+
* frame already, so it is used as is — never re-scaled.
|
|
68985
|
+
*
|
|
68984
68986
|
* Every OTHER track alive on the camera at that instant contributes its own
|
|
68985
68987
|
* nearest position the same way — a frame with three people is three boxes,
|
|
68986
68988
|
* and a recording still (no track of its own) gets everything the pipeline
|
|
@@ -69035,6 +69037,18 @@ function toRetrainClassTiers(className, label) {
|
|
|
69035
69037
|
label: kept
|
|
69036
69038
|
} : { macroClass };
|
|
69037
69039
|
}
|
|
69040
|
+
/** A verdict on the wire: the operator's class split into tiers once, here. */
|
|
69041
|
+
function toRetrainVerdict(input) {
|
|
69042
|
+
const tiers = input.suggestedClass !== void 0 ? toRetrainClassTiers(input.suggestedClass, void 0) : null;
|
|
69043
|
+
return {
|
|
69044
|
+
verdict: input.verdict,
|
|
69045
|
+
trackId: input.trackId,
|
|
69046
|
+
...input.suggestedClass !== void 0 ? { suggestedClass: input.suggestedClass } : {},
|
|
69047
|
+
...tiers !== null ? { suggestedMacroClass: tiers.macroClass } : {},
|
|
69048
|
+
...tiers?.label !== void 0 ? { suggestedLabel: tiers.label } : {},
|
|
69049
|
+
...input.at !== void 0 ? { at: input.at } : {}
|
|
69050
|
+
};
|
|
69051
|
+
}
|
|
69038
69052
|
/** A pixel box as a clamped normalised one, or `null` when nothing is left. */
|
|
69039
69053
|
function normalise(box, frameWidth, frameHeight) {
|
|
69040
69054
|
if (frameWidth === void 0 || frameHeight === void 0) return null;
|
|
@@ -69092,6 +69106,22 @@ function boxFor(track, bbox, basis, deltaMs, score) {
|
|
|
69092
69106
|
deltaMs
|
|
69093
69107
|
};
|
|
69094
69108
|
}
|
|
69109
|
+
/** The box a notification verdict froze, or `null` when the event carried none. */
|
|
69110
|
+
function boxOfVerdict(subject) {
|
|
69111
|
+
const box = subject.bbox;
|
|
69112
|
+
if (box === void 0) return null;
|
|
69113
|
+
const clamped = normalise(box, 1, 1);
|
|
69114
|
+
if (clamped === null) return null;
|
|
69115
|
+
const tiers = toRetrainClassTiers(subject.className, subject.label);
|
|
69116
|
+
return {
|
|
69117
|
+
bbox: clamped,
|
|
69118
|
+
macroClass: tiers.macroClass,
|
|
69119
|
+
...tiers.label !== void 0 ? { label: tiers.label } : {},
|
|
69120
|
+
trackId: subject.trackId,
|
|
69121
|
+
basis: "verdict",
|
|
69122
|
+
deltaMs: 0
|
|
69123
|
+
};
|
|
69124
|
+
}
|
|
69095
69125
|
/** The own track's box: the recorded subject box first, the nearest position second. */
|
|
69096
69126
|
function ownBox(input, tolerance) {
|
|
69097
69127
|
const track = input.ownTrack;
|
|
@@ -69114,10 +69144,13 @@ function pipelineBoxesForFrame(input) {
|
|
|
69114
69144
|
const out = [];
|
|
69115
69145
|
const own = ownBox(input, tolerance);
|
|
69116
69146
|
if (own !== null) out.push(own);
|
|
69147
|
+
const verdictBox = input.verdictSubject !== void 0 ? boxOfVerdict(input.verdictSubject) : null;
|
|
69148
|
+
if (verdictBox !== null) out.push(verdictBox);
|
|
69117
69149
|
const at = input.frame.capturedAt;
|
|
69118
69150
|
if (at === void 0) return out;
|
|
69119
69151
|
const ownId = input.frame.trackId;
|
|
69120
69152
|
const seen = new Set(ownId !== void 0 ? [ownId] : []);
|
|
69153
|
+
if (input.verdictSubject !== void 0) seen.add(input.verdictSubject.trackId);
|
|
69121
69154
|
for (const track of input.neighbours) {
|
|
69122
69155
|
if (seen.has(track.trackId) || track.deviceId !== input.frame.deviceId) continue;
|
|
69123
69156
|
seen.add(track.trackId);
|
|
@@ -82367,10 +82400,18 @@ function parseActions(raw) {
|
|
|
82367
82400
|
for (const entry of raw) {
|
|
82368
82401
|
const parsed = NcRuleActionSchema.safeParse(entry);
|
|
82369
82402
|
if (!parsed.success) return null;
|
|
82370
|
-
out.push(parsed.data);
|
|
82403
|
+
out.push(normalizeNcAction(parsed.data));
|
|
82371
82404
|
}
|
|
82372
82405
|
return out;
|
|
82373
82406
|
}
|
|
82407
|
+
/** Does a stored row still carry a pre-D983 cap step (`deviceId`, no `target`)? */
|
|
82408
|
+
function hasLegacyTarget(raw) {
|
|
82409
|
+
if (!Array.isArray(raw)) return false;
|
|
82410
|
+
return raw.some((entry) => {
|
|
82411
|
+
const parsed = NcRuleActionSchema.safeParse(entry);
|
|
82412
|
+
return parsed.success && parsed.data.kind === "cap" && parsed.data.target === void 0;
|
|
82413
|
+
});
|
|
82414
|
+
}
|
|
82374
82415
|
function rowToSequence(id, body) {
|
|
82375
82416
|
const actions = parseActions(body.actions);
|
|
82376
82417
|
if (actions === null) return null;
|
|
@@ -82409,6 +82450,7 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82409
82450
|
try {
|
|
82410
82451
|
const { records } = await this.kind.query({ limit: 1e4 });
|
|
82411
82452
|
const next = /* @__PURE__ */ new Map();
|
|
82453
|
+
const legacyRows = [];
|
|
82412
82454
|
let skipped = 0;
|
|
82413
82455
|
for (const row of records) {
|
|
82414
82456
|
const sequence = rowToSequence(row.id, row.data);
|
|
@@ -82417,9 +82459,11 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82417
82459
|
continue;
|
|
82418
82460
|
}
|
|
82419
82461
|
next.set(sequence.id, sequence);
|
|
82462
|
+
if (hasLegacyTarget(row.data.actions)) legacyRows.push(row.id);
|
|
82420
82463
|
}
|
|
82421
82464
|
this.byId.clear();
|
|
82422
82465
|
for (const [id, seq] of next) this.byId.set(id, seq);
|
|
82466
|
+
await this.rewriteLegacyRows(legacyRows, records);
|
|
82423
82467
|
if (skipped > 0) this.logger.warn("sequence rows skipped as malformed — bindings to them will miss", { meta: { skipped } });
|
|
82424
82468
|
} catch (err) {
|
|
82425
82469
|
this.logger.warn("sequence load failed — keeping the sequences already in memory", { meta: {
|
|
@@ -82428,6 +82472,28 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82428
82472
|
} });
|
|
82429
82473
|
}
|
|
82430
82474
|
}
|
|
82475
|
+
/**
|
|
82476
|
+
* One-shot, idempotent (D983): a row whose steps still carry `deviceId` is
|
|
82477
|
+
* stored again in the target shape. A failed write leaves the row as it was —
|
|
82478
|
+
* it is still READ as the new shape — and is on the record.
|
|
82479
|
+
*/
|
|
82480
|
+
async rewriteLegacyRows(ids, records) {
|
|
82481
|
+
for (const id of ids) {
|
|
82482
|
+
const sequence = this.byId.get(id) ?? null;
|
|
82483
|
+
const row = records.find((r) => r.id === id);
|
|
82484
|
+
if (sequence === null || row === void 0) continue;
|
|
82485
|
+
try {
|
|
82486
|
+
const createdAt = row.data.createdAt;
|
|
82487
|
+
await this.persist(sequence, typeof createdAt === "number" && Number.isFinite(createdAt) ? createdAt : this.now(), this.now());
|
|
82488
|
+
this.logger.info("notification sequence rewritten to the target shape", { meta: { sequenceId: id } });
|
|
82489
|
+
} catch (err) {
|
|
82490
|
+
this.logger.warn("notification sequence could not be rewritten — it is still read as the target shape", { meta: {
|
|
82491
|
+
sequenceId: id,
|
|
82492
|
+
error: String(err)
|
|
82493
|
+
} });
|
|
82494
|
+
}
|
|
82495
|
+
}
|
|
82496
|
+
}
|
|
82431
82497
|
list() {
|
|
82432
82498
|
return [...this.byId.values()].toSorted((a, b) => a.name.localeCompare(b.name));
|
|
82433
82499
|
}
|
|
@@ -82447,7 +82513,7 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82447
82513
|
id: randomUUID(),
|
|
82448
82514
|
name: input.name,
|
|
82449
82515
|
...input.minDelaySec !== void 0 ? { minDelaySec: input.minDelaySec } : {},
|
|
82450
|
-
actions:
|
|
82516
|
+
actions: input.actions.map(normalizeNcAction)
|
|
82451
82517
|
};
|
|
82452
82518
|
await this.persist(sequence, now, now);
|
|
82453
82519
|
this.byId.set(sequence.id, sequence);
|
|
@@ -82463,7 +82529,7 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82463
82529
|
id: sequence.id,
|
|
82464
82530
|
name: sequence.name,
|
|
82465
82531
|
...sequence.minDelaySec !== void 0 ? { minDelaySec: sequence.minDelaySec } : {},
|
|
82466
|
-
actions:
|
|
82532
|
+
actions: sequence.actions.map(normalizeNcAction)
|
|
82467
82533
|
};
|
|
82468
82534
|
await this.persist(stored, now, now);
|
|
82469
82535
|
this.byId.set(stored.id, stored);
|
|
@@ -82476,7 +82542,7 @@ var NcSequenceStore = class NcSequenceStore {
|
|
|
82476
82542
|
id: sequenceId,
|
|
82477
82543
|
name: input.name,
|
|
82478
82544
|
...input.minDelaySec !== void 0 ? { minDelaySec: input.minDelaySec } : {},
|
|
82479
|
-
actions:
|
|
82545
|
+
actions: input.actions.map(normalizeNcAction)
|
|
82480
82546
|
};
|
|
82481
82547
|
const createdAt = await this.readCreatedAt(sequenceId, now);
|
|
82482
82548
|
await this.persist(sequence, createdAt, now);
|
|
@@ -82544,7 +82610,11 @@ var NC_DETECTION_VERDICTS_COLUMNS = [
|
|
|
82544
82610
|
var NcDetectionVerdictRecordSchema = object({
|
|
82545
82611
|
trackId: string().min(1),
|
|
82546
82612
|
deviceId: number().int(),
|
|
82547
|
-
verdict: _enum([
|
|
82613
|
+
verdict: _enum([
|
|
82614
|
+
"correct",
|
|
82615
|
+
"wrong",
|
|
82616
|
+
"wrong-label"
|
|
82617
|
+
]),
|
|
82548
82618
|
/** The class the operator said it really was. Only with `wrong`. */
|
|
82549
82619
|
suggestedClass: string().min(1).optional(),
|
|
82550
82620
|
/** Whose notification it was (the token's frozen owner), NOT who tapped. */
|
|
@@ -82579,6 +82649,16 @@ var NcDetectionVerdictLedger = class {
|
|
|
82579
82649
|
logger: deps.logger
|
|
82580
82650
|
});
|
|
82581
82651
|
}
|
|
82652
|
+
/** The answers recorded for these tracks (a track nobody answered is absent).
|
|
82653
|
+
* Reads the in-memory mirror: no I/O, so a listing never waits on it. */
|
|
82654
|
+
forTracks(trackIds) {
|
|
82655
|
+
const out = /* @__PURE__ */ new Map();
|
|
82656
|
+
for (const id of trackIds) {
|
|
82657
|
+
const row = this.ledger.get(id);
|
|
82658
|
+
if (row !== void 0) out.set(id, row);
|
|
82659
|
+
}
|
|
82660
|
+
return out;
|
|
82661
|
+
}
|
|
82582
82662
|
/** Write-through; throws on a failed write so the tap reports it. */
|
|
82583
82663
|
async record(row) {
|
|
82584
82664
|
await this.ledger.put(NcDetectionVerdictRecordSchema.parse(row));
|
|
@@ -82712,10 +82792,33 @@ function pruneHookBindings(bindings, field, isDead, notes) {
|
|
|
82712
82792
|
kept.push(binding);
|
|
82713
82793
|
continue;
|
|
82714
82794
|
}
|
|
82715
|
-
if (binding.action.kind === "cap"
|
|
82716
|
-
|
|
82717
|
-
|
|
82718
|
-
|
|
82795
|
+
if (binding.action.kind === "cap") {
|
|
82796
|
+
const { target } = normalizeNcCapTarget(binding.action);
|
|
82797
|
+
if (target.kind === "devices") {
|
|
82798
|
+
const dead = target.ids.filter(isDead);
|
|
82799
|
+
if (dead.length === target.ids.length) {
|
|
82800
|
+
changed = true;
|
|
82801
|
+
notes.removed(field, deviceSubjects(dead), "binding-removed");
|
|
82802
|
+
continue;
|
|
82803
|
+
}
|
|
82804
|
+
if (dead.length > 0) {
|
|
82805
|
+
changed = true;
|
|
82806
|
+
notes.removed(field, deviceSubjects(dead), "binding-removed");
|
|
82807
|
+
const alive = target.ids.filter((id) => !isDead(id));
|
|
82808
|
+
kept.push({
|
|
82809
|
+
...binding,
|
|
82810
|
+
action: normalizeNcAction({
|
|
82811
|
+
...binding.action,
|
|
82812
|
+
deviceId: void 0,
|
|
82813
|
+
target: {
|
|
82814
|
+
kind: "devices",
|
|
82815
|
+
ids: alive
|
|
82816
|
+
}
|
|
82817
|
+
})
|
|
82818
|
+
});
|
|
82819
|
+
continue;
|
|
82820
|
+
}
|
|
82821
|
+
}
|
|
82719
82822
|
}
|
|
82720
82823
|
kept.push(binding);
|
|
82721
82824
|
}
|
|
@@ -82871,7 +82974,11 @@ function referencedDeviceIds(snapshot) {
|
|
|
82871
82974
|
add(c.systemEvent?.deviceIds);
|
|
82872
82975
|
if (c.deviceState !== void 0) ids.add(c.deviceState.deviceId);
|
|
82873
82976
|
if (c.scene?.deviceId !== void 0) ids.add(c.scene.deviceId);
|
|
82874
|
-
for (const binding of [...rule.actions?.onTrigger ?? [], ...rule.actions?.onTriggerOff ?? []])
|
|
82977
|
+
for (const binding of [...rule.actions?.onTrigger ?? [], ...rule.actions?.onTriggerOff ?? []]) {
|
|
82978
|
+
if (binding.kind !== "do" || binding.action.kind !== "cap") continue;
|
|
82979
|
+
const { target } = normalizeNcCapTarget(binding.action);
|
|
82980
|
+
if (target.kind === "devices") add(target.ids);
|
|
82981
|
+
}
|
|
82875
82982
|
}
|
|
82876
82983
|
for (const rule of snapshot.timelapse) add(rule.deviceIds);
|
|
82877
82984
|
for (const rule of snapshot.summary) add(rule.deviceIds);
|
|
@@ -83542,6 +83649,8 @@ var NcDeviceStateCache = class {
|
|
|
83542
83649
|
//#region src/notification-center/detection-verdict-buttons.ts
|
|
83543
83650
|
var VERDICT_CORRECT_ID = "detection-verdict-correct";
|
|
83544
83651
|
var VERDICT_WRONG_ID = "detection-verdict-wrong";
|
|
83652
|
+
/** Wrong LABEL, right class — only for a subject that has a label. */
|
|
83653
|
+
var VERDICT_WRONG_LABEL_ID = "detection-verdict-wrong-label";
|
|
83545
83654
|
/** `detection-verdict-wrong:<class>` — Wrong, and what it really was. */
|
|
83546
83655
|
var VERDICT_WRONG_AS_PREFIX = "detection-verdict-wrong:";
|
|
83547
83656
|
/** The macro classes offered as "it was really…". Short on purpose. */
|
|
@@ -83558,6 +83667,15 @@ function verdictButtonRefusal(subject) {
|
|
|
83558
83667
|
if (subject.ownerUserId === void 0) return "unowned-target";
|
|
83559
83668
|
return null;
|
|
83560
83669
|
}
|
|
83670
|
+
/**
|
|
83671
|
+
* Does the notified subject carry a label below its macro class — a sub-class
|
|
83672
|
+
* (`dog` under `animal`), a recognised name, a plate? The same tier split the
|
|
83673
|
+
* retrain annotations use, so "has a label" means one thing in both places.
|
|
83674
|
+
*/
|
|
83675
|
+
function subjectHasLabel(className, label) {
|
|
83676
|
+
if (className === void 0) return false;
|
|
83677
|
+
return toRetrainClassTiers(className, label).label !== void 0;
|
|
83678
|
+
}
|
|
83561
83679
|
/** The classes worth offering for a subject of `className`. */
|
|
83562
83680
|
function verdictClassChoices(className) {
|
|
83563
83681
|
return VERDICT_CLASS_CHOICES.filter((c) => c !== className).slice(0, VERDICT_MAX_CLASS_CHOICES);
|
|
@@ -83569,13 +83687,17 @@ function verdictClassChoices(className) {
|
|
|
83569
83687
|
* when the channel declared room for a fourth button.
|
|
83570
83688
|
*/
|
|
83571
83689
|
function verdictButtonSpecs(input) {
|
|
83572
|
-
const
|
|
83690
|
+
const plain = [{
|
|
83573
83691
|
actionId: VERDICT_CORRECT_ID,
|
|
83574
83692
|
verdict: "correct"
|
|
83575
83693
|
}, {
|
|
83576
83694
|
actionId: VERDICT_WRONG_ID,
|
|
83577
83695
|
verdict: "wrong"
|
|
83578
83696
|
}];
|
|
83697
|
+
const base = subjectHasLabel(input.className, input.label) ? [...plain, {
|
|
83698
|
+
actionId: VERDICT_WRONG_LABEL_ID,
|
|
83699
|
+
verdict: "wrong-label"
|
|
83700
|
+
}] : plain;
|
|
83579
83701
|
if (input.maxActions === void 0 || input.maxActions <= 3) return base;
|
|
83580
83702
|
const room = input.maxActions - base.length;
|
|
83581
83703
|
const extra = verdictClassChoices(input.className).slice(0, room).map((suggestedClass) => ({
|
|
@@ -87306,6 +87428,8 @@ var NcDispatcher = class {
|
|
|
87306
87428
|
...target.ownerUserId !== void 0 ? { ownerUserId: target.ownerUserId } : {},
|
|
87307
87429
|
...entry.payload.subject.className !== void 0 ? { className: entry.payload.subject.className } : {},
|
|
87308
87430
|
...entry.payload.subject.trackId !== void 0 ? { trackId: entry.payload.subject.trackId } : {},
|
|
87431
|
+
...entry.payload.subject.label !== void 0 ? { label: entry.payload.subject.label } : {},
|
|
87432
|
+
...entry.payload.subject.bbox !== void 0 ? { bbox: entry.payload.subject.bbox } : {},
|
|
87309
87433
|
eventAtMs: entry.payload.subject.timestamp,
|
|
87310
87434
|
...target.maxActions !== void 0 ? { maxActions: target.maxActions } : {},
|
|
87311
87435
|
...entry.payload.subject.systemEvent !== void 0 ? { systemEvent: entry.payload.subject.systemEvent } : {}
|
|
@@ -91669,7 +91793,7 @@ var NcRuleActionRunner = class {
|
|
|
91669
91793
|
if (sequence.throttle) this.lastRunAt.set(sequence.id, now);
|
|
91670
91794
|
let stepsRun = 0;
|
|
91671
91795
|
for (const [index, action] of sequence.actions.entries()) try {
|
|
91672
|
-
await this.step(action, input.origin);
|
|
91796
|
+
await this.step(action, input.origin, sequence.id);
|
|
91673
91797
|
stepsRun += 1;
|
|
91674
91798
|
} catch (err) {
|
|
91675
91799
|
this.deps.logger.warn("rule action failed — stopping the sequence", {
|
|
@@ -91709,20 +91833,28 @@ var NcRuleActionRunner = class {
|
|
|
91709
91833
|
stepsRun
|
|
91710
91834
|
};
|
|
91711
91835
|
}
|
|
91712
|
-
async step(action, origin) {
|
|
91836
|
+
async step(action, origin, owner) {
|
|
91713
91837
|
if (action.kind === "wait") {
|
|
91714
91838
|
await this.sleep(action.seconds * 1e3);
|
|
91715
91839
|
return;
|
|
91716
91840
|
}
|
|
91717
91841
|
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
|
-
|
|
91842
|
+
const { target, actionId } = normalizeNcCapTarget(action);
|
|
91843
|
+
const deviceIds = await this.devicesOf(target, actionId, owner);
|
|
91844
|
+
for (const deviceId of deviceIds) await this.deps.actuate({
|
|
91845
|
+
deviceId,
|
|
91720
91846
|
cap: action.cap,
|
|
91721
91847
|
method: action.method,
|
|
91722
91848
|
args: action.args ?? {},
|
|
91723
91849
|
...origin !== void 0 ? { origin } : {}
|
|
91724
91850
|
});
|
|
91725
91851
|
}
|
|
91852
|
+
async devicesOf(target, actionId, owner) {
|
|
91853
|
+
if (target.kind === "devices") return target.ids;
|
|
91854
|
+
if (target.kind === "var") throw new Error("rule action refused: a sequence has no variables to resolve a target from");
|
|
91855
|
+
if (this.deps.resolveTarget === void 0) throw new Error("rule action refused: this node cannot resolve a domain target");
|
|
91856
|
+
return (await this.deps.resolveTarget(target, actionId, owner)).deviceIds;
|
|
91857
|
+
}
|
|
91726
91858
|
};
|
|
91727
91859
|
/** Force-enable a shared sequence for a button tap (always runs, still throttled). */
|
|
91728
91860
|
function asForcedSequence(sequence) {
|
|
@@ -100110,6 +100242,12 @@ function rowRefusalId(systemEvent) {
|
|
|
100110
100242
|
const value = systemEvent?.data["refusalId"];
|
|
100111
100243
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
100112
100244
|
}
|
|
100245
|
+
/** The text-catalog key of each verdict button. */
|
|
100246
|
+
var VERDICT_LABEL_KEY = {
|
|
100247
|
+
correct: "button.verdict.correct",
|
|
100248
|
+
wrong: "button.verdict.wrong",
|
|
100249
|
+
"wrong-label": "button.verdict.wrongLabel"
|
|
100250
|
+
};
|
|
100113
100251
|
/**
|
|
100114
100252
|
* The tap-through buttons for ONE delivery, each with its own single-use
|
|
100115
100253
|
* token.
|
|
@@ -100146,6 +100284,7 @@ async function mintButtons(host, input) {
|
|
|
100146
100284
|
const verdictOwner = input.ownerUserId;
|
|
100147
100285
|
const verdictButtons = verdictRefusal !== null || verdictTrackId === void 0 || verdictOwner === void 0 ? [] : verdictButtonSpecs({
|
|
100148
100286
|
className: input.className,
|
|
100287
|
+
label: input.label,
|
|
100149
100288
|
maxActions: input.maxActions
|
|
100150
100289
|
}).map((spec) => {
|
|
100151
100290
|
const id = randomUUID();
|
|
@@ -100163,6 +100302,11 @@ async function mintButtons(host, input) {
|
|
|
100163
100302
|
...spec.suggestedClass !== void 0 ? { suggestedClass: spec.suggestedClass } : {},
|
|
100164
100303
|
...input.maxActions === 0 ? { viaLink: true } : {},
|
|
100165
100304
|
...input.eventAtMs !== void 0 ? { eventAtMs: input.eventAtMs } : {},
|
|
100305
|
+
...input.className !== void 0 ? { subject: {
|
|
100306
|
+
className: input.className,
|
|
100307
|
+
...input.label !== void 0 ? { label: input.label } : {},
|
|
100308
|
+
...input.bbox !== void 0 ? { bbox: input.bbox } : {}
|
|
100309
|
+
} } : {},
|
|
100166
100310
|
deviceId: input.deviceId,
|
|
100167
100311
|
actionId: spec.actionId,
|
|
100168
100312
|
targetId: input.targetId,
|
|
@@ -100171,7 +100315,7 @@ async function mintButtons(host, input) {
|
|
|
100171
100315
|
});
|
|
100172
100316
|
return {
|
|
100173
100317
|
id: spec.actionId,
|
|
100174
|
-
label: spec.suggestedClass === void 0 ? host.texts.text({ key: spec.verdict
|
|
100318
|
+
label: spec.suggestedClass === void 0 ? host.texts.text({ key: VERDICT_LABEL_KEY[spec.verdict] }) : host.texts.text({
|
|
100175
100319
|
key: "button.verdict.wrongAs",
|
|
100176
100320
|
vars: { class: spec.suggestedClass }
|
|
100177
100321
|
}),
|
|
@@ -100630,6 +100774,18 @@ var VERDICT_FRAME_REFUSAL_COPY = {
|
|
|
100630
100774
|
"still-busy": "The track is gone and the recorder is busy — nothing was changed, try again later",
|
|
100631
100775
|
failed: "The track is gone and its frame could not be saved — nothing was changed"
|
|
100632
100776
|
};
|
|
100777
|
+
/** The grant's frozen subject, in the shape the retrain still stores it in. */
|
|
100778
|
+
function verdictSubjectOf(grant, subject, at) {
|
|
100779
|
+
return {
|
|
100780
|
+
trackId: grant.trackId,
|
|
100781
|
+
className: subject.className,
|
|
100782
|
+
...subject.label !== void 0 ? { label: subject.label } : {},
|
|
100783
|
+
...subject.bbox !== void 0 ? { bbox: subject.bbox } : {},
|
|
100784
|
+
verdict: grant.verdict,
|
|
100785
|
+
...grant.suggestedClass !== void 0 ? { suggestedClass: grant.suggestedClass } : {},
|
|
100786
|
+
at
|
|
100787
|
+
};
|
|
100788
|
+
}
|
|
100633
100789
|
/**
|
|
100634
100790
|
* The track is gone (aged out, or discarded as a still object): the camera's
|
|
100635
100791
|
* RECORDING still covers the instant, so the verdict lands a frame there
|
|
@@ -100652,7 +100808,8 @@ async function landFrameFromRecording(host, grant) {
|
|
|
100652
100808
|
}
|
|
100653
100809
|
const landed = await addFrame({
|
|
100654
100810
|
deviceId: grant.deviceId,
|
|
100655
|
-
epochMs: grant.eventAtMs
|
|
100811
|
+
epochMs: grant.eventAtMs,
|
|
100812
|
+
...grant.subject !== void 0 ? { subject: verdictSubjectOf(grant, grant.subject, host.now()) } : {}
|
|
100656
100813
|
});
|
|
100657
100814
|
if (!landed.ok) {
|
|
100658
100815
|
host.logger.warn("detection verdict dropped — the track is gone and the recording refused", {
|
|
@@ -101613,6 +101770,7 @@ function buildEntries(host, rule, subject, kind, matchedOn, userTargets = [], or
|
|
|
101613
101770
|
...alarmSource?.eventId !== void 0 ? { eventId: alarmSource.eventId } : hasEventMedia ? { eventId: subject.recordId } : {},
|
|
101614
101771
|
className: subject.classNames[0] ?? subject.sensorKind ?? "event",
|
|
101615
101772
|
...subject.label !== void 0 ? { label: subject.label } : {},
|
|
101773
|
+
...subject.bbox !== void 0 ? { bbox: subject.bbox } : {},
|
|
101616
101774
|
...subject.labelKind !== void 0 ? { labelKind: subject.labelKind } : {},
|
|
101617
101775
|
...subject.confidence !== void 0 ? { confidence: subject.confidence } : {},
|
|
101618
101776
|
zones: renderedZones,
|
|
@@ -105933,6 +106091,8 @@ var NotificationCenter = class {
|
|
|
105933
106091
|
zoneOwners;
|
|
105934
106092
|
/** Runs a matched rule's action sequences. Null when no actuator is wired. */
|
|
105935
106093
|
actionRunner;
|
|
106094
|
+
/** Domain action targets read from the registry (D983); null without a directory. */
|
|
106095
|
+
actionTargets;
|
|
105936
106096
|
/** Grants behind the tap-through buttons. In-process and single-use — read
|
|
105937
106097
|
* `action-token.ts` before assuming anything about what a tap proves. */
|
|
105938
106098
|
actionTokens = new NcActionTokenRegistry();
|
|
@@ -106340,9 +106500,15 @@ var NotificationCenter = class {
|
|
|
106340
106500
|
});
|
|
106341
106501
|
this.livenessHoldoff = new DeviceLivenessHoldoff((event) => this.consumeEvent(event), { delayMs: deps.livenessHoldoffMs ?? (process.env.VITEST ? 0 : DEVICE_LIVENESS_HOLDOFF_MS) });
|
|
106342
106502
|
this.nodeLivenessHoldoff = new DeviceLivenessHoldoff((event, timing) => this.consumeNodeLiveness(event, timing), { delayMs: deps.nodeLivenessHoldoffMs ?? (process.env.VITEST ? 0 : NODE_LIVENESS_HOLDOFF_MS) });
|
|
106503
|
+
const targets = deps.actionTargetDirectory !== void 0 ? new ActionTargetResolver(deps.actionTargetDirectory, this.logger.child("actions")) : null;
|
|
106504
|
+
this.actionTargets = targets;
|
|
106343
106505
|
this.actionRunner = deps.actuate !== void 0 && deps.isCapDeviceScoped !== void 0 ? new NcRuleActionRunner({
|
|
106344
106506
|
logger: this.logger.child("actions"),
|
|
106345
106507
|
actuate: (input) => this.actuateWithAttribution(input),
|
|
106508
|
+
...targets !== null ? { resolveTarget: (target, actionId, owner) => targets.resolve(target, actionId, {}, {
|
|
106509
|
+
actionId,
|
|
106510
|
+
owner
|
|
106511
|
+
}) } : {},
|
|
106346
106512
|
isDeviceScoped: deps.isCapDeviceScoped,
|
|
106347
106513
|
...deps.now !== void 0 ? { now: deps.now } : {}
|
|
106348
106514
|
}) : null;
|
|
@@ -107132,6 +107298,21 @@ var NotificationCenter = class {
|
|
|
107132
107298
|
}
|
|
107133
107299
|
};
|
|
107134
107300
|
}
|
|
107301
|
+
/**
|
|
107302
|
+
* What the operator answered to the "was this detection right?" buttons, for
|
|
107303
|
+
* the retrain page: by track, the latest answer wins. A track nobody answered
|
|
107304
|
+
* is absent.
|
|
107305
|
+
*/
|
|
107306
|
+
detectionVerdictsOf(trackIds) {
|
|
107307
|
+
const out = /* @__PURE__ */ new Map();
|
|
107308
|
+
for (const [trackId, row] of this.verdicts.forTracks(trackIds)) out.set(trackId, toRetrainVerdict({
|
|
107309
|
+
verdict: row.verdict,
|
|
107310
|
+
trackId,
|
|
107311
|
+
at: row.at,
|
|
107312
|
+
suggestedClass: row.suggestedClass
|
|
107313
|
+
}));
|
|
107314
|
+
return out;
|
|
107315
|
+
}
|
|
107135
107316
|
observeOccupancy(deviceId, snapshot, evidence = "scene") {
|
|
107136
107317
|
return observeOccupancy(this.occupancyWatchHost(), deviceId, snapshot, evidence);
|
|
107137
107318
|
}
|
|
@@ -107307,6 +107488,10 @@ var NotificationCenter = class {
|
|
|
107307
107488
|
}
|
|
107308
107489
|
};
|
|
107309
107490
|
}
|
|
107491
|
+
/** The device registry changed: a cached domain action target is stale (D983). */
|
|
107492
|
+
invalidateActionTargets() {
|
|
107493
|
+
this.actionTargets?.invalidate();
|
|
107494
|
+
}
|
|
107310
107495
|
onSystemEvent(event) {
|
|
107311
107496
|
return onSystemEvent(this.systemEventsHost(), event);
|
|
107312
107497
|
}
|
|
@@ -108780,7 +108965,9 @@ async function addVerdictFrameFromRecording(api, logger, input) {
|
|
|
108780
108965
|
}
|
|
108781
108966
|
const result = await api.addRetrainFrameFromRecording({
|
|
108782
108967
|
collectionId,
|
|
108783
|
-
|
|
108968
|
+
deviceId: input.deviceId,
|
|
108969
|
+
epochMs: input.epochMs,
|
|
108970
|
+
...input.subject !== void 0 ? { verdictSubject: input.subject } : {}
|
|
108784
108971
|
});
|
|
108785
108972
|
if (result.kind === "added") return { ok: true };
|
|
108786
108973
|
return {
|
|
@@ -109067,6 +109254,20 @@ var BuildNotificationCenter = class extends BuildNotificationCenterBase {
|
|
|
109067
109254
|
});
|
|
109068
109255
|
},
|
|
109069
109256
|
isCapDeviceScoped: isDeviceScopedCap,
|
|
109257
|
+
actionTargetDirectory: {
|
|
109258
|
+
listDeviceIdsByCaps: (capNames) => api.deviceManager.listDeviceIdsByCaps.query({ capNames: [...capNames] }),
|
|
109259
|
+
listDevices: async (deviceIds) => {
|
|
109260
|
+
return (await api.deviceManager.listAll.query({
|
|
109261
|
+
deviceIds: [...deviceIds],
|
|
109262
|
+
projection: "slim"
|
|
109263
|
+
})).map((d) => ({
|
|
109264
|
+
id: d.id,
|
|
109265
|
+
type: d.type,
|
|
109266
|
+
location: d.location,
|
|
109267
|
+
disabled: d.disabled
|
|
109268
|
+
}));
|
|
109269
|
+
}
|
|
109270
|
+
},
|
|
109070
109271
|
generateVision: async (request) => {
|
|
109071
109272
|
const result = await api.llm.generateVision.mutate({
|
|
109072
109273
|
...request.profileId !== void 0 ? { profileId: request.profileId } : {},
|
|
@@ -113692,7 +113893,7 @@ var RetrainCollectionService = class {
|
|
|
113692
113893
|
frameId: recordingFrameId(input.deviceId, input.epochMs),
|
|
113693
113894
|
deviceId: input.deviceId
|
|
113694
113895
|
});
|
|
113695
|
-
const stored = await this.storeStill(input.deviceId, input.epochMs, membershipOp === null ? [] : [membershipOp]);
|
|
113896
|
+
const stored = await this.storeStill(input.deviceId, input.epochMs, membershipOp === null ? [] : [membershipOp], input.verdictSubject);
|
|
113696
113897
|
if (stored.kind === "refused") {
|
|
113697
113898
|
this.deps.logger.info("retrain collection add refused", {
|
|
113698
113899
|
tags,
|
|
@@ -113704,11 +113905,15 @@ var RetrainCollectionService = class {
|
|
|
113704
113905
|
});
|
|
113705
113906
|
return stored;
|
|
113706
113907
|
}
|
|
113707
|
-
|
|
113708
|
-
|
|
113709
|
-
|
|
113710
|
-
|
|
113711
|
-
|
|
113908
|
+
let storedFrame = stored.frame;
|
|
113909
|
+
if (stored.reused) {
|
|
113910
|
+
await this.deps.collections.addFrame({
|
|
113911
|
+
collectionId: input.collectionId,
|
|
113912
|
+
frameId: stored.frame.frameId,
|
|
113913
|
+
deviceId: input.deviceId
|
|
113914
|
+
});
|
|
113915
|
+
if (input.verdictSubject !== void 0) storedFrame = await this.deps.frames.setVerdictSubject(stored.frame.frameId, input.verdictSubject) ?? stored.frame;
|
|
113916
|
+
}
|
|
113712
113917
|
this.deps.logger.info("retrain frame added to a collection from the recording", {
|
|
113713
113918
|
tags,
|
|
113714
113919
|
meta: {
|
|
@@ -113718,7 +113923,7 @@ var RetrainCollectionService = class {
|
|
|
113718
113923
|
reused: stored.reused
|
|
113719
113924
|
}
|
|
113720
113925
|
});
|
|
113721
|
-
const [wire] = await this.deps.retrain.toWireFrames([
|
|
113926
|
+
const [wire] = await this.deps.retrain.toWireFrames([storedFrame]);
|
|
113722
113927
|
if (wire === void 0) throw new Error("retrain: a stored still produced no wire frame");
|
|
113723
113928
|
return {
|
|
113724
113929
|
kind: "added",
|
|
@@ -113769,7 +113974,7 @@ var RetrainCollectionService = class {
|
|
|
113769
113974
|
const ids = await this.deps.collections.listFrameIds(input.collectionId);
|
|
113770
113975
|
return this.deps.retrain.toWireFrames(await this.deps.frames.getMany(ids));
|
|
113771
113976
|
}
|
|
113772
|
-
async storeStill(deviceId, epochMs, withRow) {
|
|
113977
|
+
async storeStill(deviceId, epochMs, withRow, verdictSubject) {
|
|
113773
113978
|
const existing = await this.deps.frames.get(recordingFrameId(deviceId, epochMs));
|
|
113774
113979
|
if (existing !== null) return {
|
|
113775
113980
|
kind: "stored",
|
|
@@ -113788,7 +113993,8 @@ var RetrainCollectionService = class {
|
|
|
113788
113993
|
const stored = await this.deps.frames.storeRecordingStill({
|
|
113789
113994
|
deviceId,
|
|
113790
113995
|
epochMs,
|
|
113791
|
-
bytes: still.jpeg
|
|
113996
|
+
bytes: still.jpeg,
|
|
113997
|
+
...verdictSubject !== void 0 ? { verdictSubject } : {}
|
|
113792
113998
|
}, withRow);
|
|
113793
113999
|
return stored.kind === "copied" ? {
|
|
113794
114000
|
kind: "stored",
|
|
@@ -114574,6 +114780,14 @@ function toWireFrame(f) {
|
|
|
114574
114780
|
dismissed: f.dismissed ?? []
|
|
114575
114781
|
};
|
|
114576
114782
|
}
|
|
114783
|
+
/** The answer on a frame: a track copy asks the ledger, a still carries the
|
|
114784
|
+
* subject the notification froze. */
|
|
114785
|
+
function verdictOfFrame(copy, verdicts) {
|
|
114786
|
+
if (copy.origin === "track") return verdicts.get(copy.trackId);
|
|
114787
|
+
const s = copy.verdictSubject;
|
|
114788
|
+
if (s === void 0) return void 0;
|
|
114789
|
+
return toRetrainVerdict(s);
|
|
114790
|
+
}
|
|
114577
114791
|
/**
|
|
114578
114792
|
* What the operator did with the proposals on a frame (`retrain-review.ts`).
|
|
114579
114793
|
*
|
|
@@ -114634,7 +114848,11 @@ var RetrainService = class {
|
|
|
114634
114848
|
const tracks = [];
|
|
114635
114849
|
for (const deviceId of devices) tracks.push(...await this.deps.tracks.listStaging(deviceId, limit));
|
|
114636
114850
|
const ids = tracks.map((t) => t.trackId);
|
|
114637
|
-
const [frameCounts, annotationCounts] = await Promise.all([
|
|
114851
|
+
const [frameCounts, annotationCounts, verdicts] = await Promise.all([
|
|
114852
|
+
this.deps.frames.countsByTrack(ids),
|
|
114853
|
+
this.deps.annotations.countsByTrack(ids),
|
|
114854
|
+
this.verdictsOfTracks(ids)
|
|
114855
|
+
]);
|
|
114638
114856
|
return tracks.map((t) => ({
|
|
114639
114857
|
trackId: t.trackId,
|
|
114640
114858
|
deviceId: t.deviceId,
|
|
@@ -114643,7 +114861,8 @@ var RetrainService = class {
|
|
|
114643
114861
|
firstSeen: t.firstSeen,
|
|
114644
114862
|
lastSeen: t.lastSeen,
|
|
114645
114863
|
frameCount: frameCounts.get(t.trackId) ?? 0,
|
|
114646
|
-
annotationCount: annotationCounts.get(t.trackId) ?? 0
|
|
114864
|
+
annotationCount: annotationCounts.get(t.trackId) ?? 0,
|
|
114865
|
+
...verdicts.has(t.trackId) ? { verdict: verdicts.get(t.trackId) } : {}
|
|
114647
114866
|
}));
|
|
114648
114867
|
}
|
|
114649
114868
|
/**
|
|
@@ -114693,9 +114912,14 @@ var RetrainService = class {
|
|
|
114693
114912
|
const ownTracks = /* @__PURE__ */ new Map();
|
|
114694
114913
|
const subjectBoxes = /* @__PURE__ */ new Map();
|
|
114695
114914
|
const annotationsByFrame = await this.annotationsByFrame(copies);
|
|
114915
|
+
const verdicts = await this.verdictsOf(copies);
|
|
114696
114916
|
const out = [];
|
|
114697
114917
|
for (const copy of copies) {
|
|
114698
|
-
const
|
|
114918
|
+
const verdict = verdictOfFrame(copy, verdicts);
|
|
114919
|
+
const wire = {
|
|
114920
|
+
...toWireFrame(copy),
|
|
114921
|
+
...verdict !== void 0 ? { verdict } : {}
|
|
114922
|
+
};
|
|
114699
114923
|
const collectionIds = collections?.get(copy.frameId);
|
|
114700
114924
|
const withCollections = {
|
|
114701
114925
|
...collections !== null ? {
|
|
@@ -114726,7 +114950,8 @@ var RetrainService = class {
|
|
|
114726
114950
|
},
|
|
114727
114951
|
ownTrack: trackId !== "" ? ownTracks.get(trackId) ?? null : null,
|
|
114728
114952
|
ownSubjectBox: trackId !== "" ? subjectBoxes.get(trackId)?.get(copy.sourceMediaId) ?? null : null,
|
|
114729
|
-
neighbours
|
|
114953
|
+
neighbours,
|
|
114954
|
+
...copy.verdictSubject !== void 0 ? { verdictSubject: copy.verdictSubject } : {}
|
|
114730
114955
|
});
|
|
114731
114956
|
out.push({
|
|
114732
114957
|
...withCollections,
|
|
@@ -114736,6 +114961,22 @@ var RetrainService = class {
|
|
|
114736
114961
|
}
|
|
114737
114962
|
return out;
|
|
114738
114963
|
}
|
|
114964
|
+
/** The verdicts of the tracks these frames were copied from. */
|
|
114965
|
+
async verdictsOf(copies) {
|
|
114966
|
+
return this.verdictsOfTracks(copies.flatMap((c) => c.origin === "track" ? [c.trackId] : []));
|
|
114967
|
+
}
|
|
114968
|
+
async verdictsOfTracks(trackIds) {
|
|
114969
|
+
const port = this.deps.verdicts;
|
|
114970
|
+
const ids = [...new Set(trackIds)];
|
|
114971
|
+
if (port === void 0 || ids.length === 0) return /* @__PURE__ */ new Map();
|
|
114972
|
+
return port.forTracks(ids).catch((err) => {
|
|
114973
|
+
this.deps.logger.warn("retrain frames: verdicts unreadable", { meta: {
|
|
114974
|
+
tracks: ids.length,
|
|
114975
|
+
error: String(err)
|
|
114976
|
+
} });
|
|
114977
|
+
return /* @__PURE__ */ new Map();
|
|
114978
|
+
});
|
|
114979
|
+
}
|
|
114739
114980
|
/** The URLs of a frame's pixels, when a data plane is served for them. */
|
|
114740
114981
|
frameUrls(frameId) {
|
|
114741
114982
|
const frameUrl = this.deps.frameUrl;
|
|
@@ -116852,6 +117093,7 @@ var BuildStores = class extends BuildStoresBase {
|
|
|
116852
117093
|
subjectBoxes: (trackId, deviceId) => mediaStore.listSubjectBoxesByOwner("track", trackId, deviceId)
|
|
116853
117094
|
},
|
|
116854
117095
|
memberships: retrainCollectionStore,
|
|
117096
|
+
verdicts: { forTracks: async (trackIds) => this.notificationCenter?.detectionVerdictsOf(trackIds) ?? /* @__PURE__ */ new Map() },
|
|
116855
117097
|
frameUrl: (frameId, size) => retrainFramePath(this.ctx.id, frameId, size)
|
|
116856
117098
|
});
|
|
116857
117099
|
this.retrain = retrain;
|
|
@@ -122563,7 +122805,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
122563
122805
|
onBindingsChanged: (data) => this.handleBindingsChangedEvent(data),
|
|
122564
122806
|
onDeviceUnregistered: (deviceId) => this.handleDeviceUnregisteredEvent(deviceId),
|
|
122565
122807
|
onClusterTopology: (nodes) => this.nodeLiveness.applySnapshot(nodes, Date.now()),
|
|
122566
|
-
onSystemEvent: (event) => this.notificationCenter?.onSystemEvent(event)
|
|
122808
|
+
onSystemEvent: (event) => this.notificationCenter?.onSystemEvent(event),
|
|
122809
|
+
onDeviceRegistryChange: () => this.notificationCenter?.invalidateActionTargets()
|
|
122567
122810
|
});
|
|
122568
122811
|
await step("startTrackingTapes", () => this.startTrackingTapes(this.isPostProcessingNode));
|
|
122569
122812
|
if (this.isPostProcessingNode) await step("startEmbeddingDispatcher", () => this.startEmbeddingDispatcher(logger, transport));
|