@camstack/addon-post-analysis 1.2.316 → 1.2.319
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{clip-model-registry-D-zzCBKK.js → clip-model-registry-BjYpZuuI.js} +9 -5
- package/dist/{clip-model-registry-Dkv8MUCO.mjs → clip-model-registry-DSqobJfx.mjs} +9 -5
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +1 -1
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-BNvVKYGi.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CKHzDA_B.mjs} +2 -2
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Bz37odzX.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-Cpm1aEUE.mjs → hostInit-DDDjJDA6.mjs} +2 -2
- package/dist/pipeline-analytics/index.js +406 -30
- package/dist/pipeline-analytics/index.mjs +406 -30
- 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-BAqKeExF.mjs +0 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as NC_ALARM_SYSTEM_EVENT_KINDS, $n as notificationRulesCapability, $r as object, $t as SCENE_DEFAULT_UNCOVERED_POLICY, A as EMBEDDING_REQUIREMENTS_FAILED, Ar as canonicalHash, At as NcScheduleSchema, B as ListTrackRelationsInputSchema, Bn as isAudioClassName, Br as hydrateSchema, Bt as OPS_LOG_DEFAULT_LIMIT, C as DEFAULT_EVENT_COLOR, Cn as buildEventKindDescriptor, Cr as systemEventSummaryScheduleOf, Ct as NcConditionDescriptorSchema, D as DeclaredDevices, Dn as describeSystemEventDeliveryProblem, Dr as vectorDimFromBase64, Dt as NcRuleSchema, E as DETECTION_PIPELINE_CAP_NAME, En as deriveRecordingMode, Er as templateVarsFor, Et as NcRulePatchSchema, F as EXPORT_DENSE_MAX_RANGES, Fn as evictionPolicyOfLocation, Fr as BaseAddon, Ft as NcSystemEventKindSchema, G as MAX_BIRTH_LATENCY_PROXY_MS, Gn as isRetiredClearKey, Gr as ZodObject, Gt as RebuildObjectEmbeddingsRefusalSchema, H as LockStateSchema, Hn as isEventOwnerType, Hr as nodePin, I as FIRST_LEVEL_MACRO_CLASSES, In as faceGalleryCapability, Ir as CamProfileSchema, It as NcTaxonomySchema, J as MOTION_CLOSE_AFTER_MS, Jn as isSystemEventSummaryRule, Jr as boolean, Jt as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, K as MAX_TRACK_PURITIES, Kn as isScheduleActive, Kr as _enum, Kt as RetrainStatusSchema, L as FULL_IMAGE_BBOX, Ln as failureContributionCapability, Lr as createEvent, Lt as NcTemplatePreviewInputSchema, M as EVENT_DENSITY_BATCH_MAX, Mr as isSourceCap, Mt as NcSnoozeSchema, N as EVENT_KIND_BY_CAP, Nr as DeviceType, Nt as NcSnoozeSuppressedSchema, O as DetectionSourceSchema, On as describeSystemEventFamilyProblem, Or as zoneAnalyticsCapability, Ot as NcRuleTargetSchema, P as EVENT_OWNER_TYPES, Pn as encodeVectorBase64, Pr as errMsg, Pt as NcStateSummarySectionIdSchema, Q as NC_ALARM_DELAY_MAX_SEC, Qn as memoizePinnedFfmpeg, Qr as number, Qt as SCENE_DEFAULT_QUIET_SECONDS, R as FailureCounters, Rn as gifDeriveSpeed, Rr as customAction, Rt as NcTemplatePreviewSchema, S as CoverStateSchema, Sn as audioModeOf, Sr as systemEventFilterApplies, St as NcAlarmSettingsPatchSchema, T as DETECTION_MACRO_CLASSES, Tn as cosineSimilarity$1, Tr as templateCarriesSummary, Tt as NcRuleInputSchema, U as MAX_ARCHIVED_DEBUG_NOTES, Un as isKnownTemplateVar, Ut as RECORDING_EXPORT_MAX_READ_BYTES, V as ListTrackRelationsResultSchema, Vn as isDetectionMacroClass, Vr as isDeviceScopedCap, Vt as OpsLogEntrySchema, W as MAX_BIRTH_DECISION_RECORDS, Wn as isMediaOwnerType, Wr as sleep$1, Wt as RECORDING_SOURCE_CAMSTACK_ADDON, X as MotionTriggeredBySchema, Xn as kebabToCamel, Xr as literal, Xt as SCENE_DEFAULT_CHECK_INTERVAL_SEC, Y as MediaFileKindEnum, Yn as isVectorIndexDimConflict, Yr as discriminatedUnion, Yt as SCENE_DEFAULT_ANCHOR_THRESHOLD, Z as NC_ALARM_DELAY_FIELDS, Zn as mayWriteToLocation, Zr as looseObject, Zt as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, _ as BaseDevice, _n as alarmPanelCapability, _r as servedTemplateVars, _t as NC_TAXONOMY, a as CLIP_EMBEDDING_STEP_ID, ai as tuple, an as SetTrackRelationInputSchema, ar as readMotionTriggeredBy, at as NC_CLIP_RETENTION_MAX_SEC, b as ClearTrackRelationInputSchema, bn as assertTimelapseCadences, br as systemEventDeliveryProblems, bt as NcAlarmSensorsInputSchema, c as resolveClusterModelPin, ci as EventCategory, cn as TimelapseRuleInputSchema, cr as resolveLocationMode, ct as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, d as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, dn as TrackPuritySchema, dr as ruleBelongsToAlarm$1, dt as NC_GROUPING_MAX_SEC, ei as partialRecord, en as SCENE_DIVERGED, er as occupancyScope, et as NC_ALARM_TRIGGERED_MAX_SEC, f as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, fn as TrackRelationKindSchema, fr as ruleDeviceCompatCapQueries, ft as NC_GROUPING_MIN_SEC, g as BIRTH_DECISION_DEFAULT_LIMIT, gn as addonWidgetsSourceCapability, gr as sensorRaisedOf, gt as NC_TANK_SYSTEM_EVENT_KINDS, h as ArchivedDebugNoteSchema, hn as TrackSourceSchema, hr as sceneMonitorCapability, ht as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, ii as templateLiteral, in as SetTrackPurityResultSchema, ir as readDeviceStateFrom, it as NC_CLIP_PRE_ROLL_DEFAULT_SEC, j as EMBEDDING_REQUIREMENTS_UNAVAILABLE, jn as embeddingRefusalOf, jr as evaluateSensorEdge, jt as NcSnoozeInputSchema, k as EMBEDDING_MODEL_FAILED, kr as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, kt as NcRuleUpdateInputSchema, l as APPEARANCE_BIN_COUNT, ln as TimelapseRulePatchSchema, lr as resolveModeDelays, lt as NC_DEFAULT_SNOOZE_MINUTES, m as AlarmArmModeSchema, mn as TrackSideSchema, mr as ruleKindOf, mt as NC_SNOOZE_MAX_MINUTES, ni as strictObject, nn as SceneMonitorSchema, nr as pipelineAnalyticsCapability, nt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, o as FACE_EMBEDDING_STEP_ID, oi as union, on as TIMELAPSE_DENSE_FLOOR_SEC, or as readTimelapseGeneratedAt, ot as NC_CONDITION_CATALOG, p as AUDIO_MACRO_LABELS, pn as TrackRelationSchema, pr as ruleGroupingApplies, pt as NC_SENSOR_TRANSITION_KINDS, q as MAX_TRACK_RELATIONS, qn as isSystemDelivery, qr as array, qt as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, ri as string, rn as SetTrackPurityInputSchema, rr as plateGalleryCapability, rt as NC_CLIP_POST_ROLL_DEFAULT_SEC, s as readClusterModelPinStrict, si as unknown, sn as TRACK_RELATIONS_DEFAULT_LIMIT, sr as resolveClipSearchMinScore, st as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, t as BUILTIN_CLIP_MODELS, ti as record, tn as SCENE_RESET_RECAPTURES, tt as NC_AUDIO_CONFIRM_HITS_DEFAULT, u as APPEARANCE_BLOCKS, un as TimelapseRuleSchema, ut as NC_GROUPING_DEFAULT_SEC, v as BirthDecisionRecordSchema, vn as applyModeDelaysEdits, vr as storageOccupancyCapability, vt as NC_TEMPLATE_VARS, w as DEFAULT_TIMELAPSE_PREVIEW_TEXT, wn as consumableLowPercentOf, wr as systemEventSummarySplitOf, wt as NcConditionsSchema, x as ClearTrackRelationResultSchema, xn as audioMetricsCapability, xr as systemEventFamilyProblems, xt as NcAlarmSensorsSchema, y as COCO_TO_MACRO, yn as applyNonBlockingEdit, yr as subKindsOf, yt as NcAlarmConfigSchema, z as LabelAttributionSchema, zn as gifFromMp4Args, zr as defineCustomActions, zt as NcTemplateVarDescriptorSchema } from "../clip-model-registry-
|
|
1
|
+
import { $ as NC_ALARM_SYSTEM_EVENT_KINDS, $n as notificationRulesCapability, $r as object, $t as SCENE_DEFAULT_UNCOVERED_POLICY, A as EMBEDDING_REQUIREMENTS_FAILED, Ar as canonicalHash, At as NcScheduleSchema, B as ListTrackRelationsInputSchema, Bn as isAudioClassName, Br as hydrateSchema, Bt as OPS_LOG_DEFAULT_LIMIT, C as DEFAULT_EVENT_COLOR, Cn as buildEventKindDescriptor, Cr as systemEventSummaryScheduleOf, Ct as NcConditionDescriptorSchema, D as DeclaredDevices, Dn as describeSystemEventDeliveryProblem, Dr as vectorDimFromBase64, Dt as NcRuleSchema, E as DETECTION_PIPELINE_CAP_NAME, En as deriveRecordingMode, Er as templateVarsFor, Et as NcRulePatchSchema, F as EXPORT_DENSE_MAX_RANGES, Fn as evictionPolicyOfLocation, Fr as BaseAddon, Ft as NcSystemEventKindSchema, G as MAX_BIRTH_LATENCY_PROXY_MS, Gn as isRetiredClearKey, Gr as ZodObject, Gt as RebuildObjectEmbeddingsRefusalSchema, H as LockStateSchema, Hn as isEventOwnerType, Hr as nodePin, I as FIRST_LEVEL_MACRO_CLASSES, In as faceGalleryCapability, Ir as CamProfileSchema, It as NcTaxonomySchema, J as MOTION_CLOSE_AFTER_MS, Jn as isSystemEventSummaryRule, Jr as boolean, Jt as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, K as MAX_TRACK_PURITIES, Kn as isScheduleActive, Kr as _enum, Kt as RetrainStatusSchema, L as FULL_IMAGE_BBOX, Ln as failureContributionCapability, Lr as createEvent, Lt as NcTemplatePreviewInputSchema, M as EVENT_DENSITY_BATCH_MAX, Mr as isSourceCap, Mt as NcSnoozeSchema, N as EVENT_KIND_BY_CAP, Nr as DeviceType, Nt as NcSnoozeSuppressedSchema, O as DetectionSourceSchema, On as describeSystemEventFamilyProblem, Or as zoneAnalyticsCapability, Ot as NcRuleTargetSchema, P as EVENT_OWNER_TYPES, Pn as encodeVectorBase64, Pr as errMsg, Pt as NcStateSummarySectionIdSchema, Q as NC_ALARM_DELAY_MAX_SEC, Qn as memoizePinnedFfmpeg, Qr as number, Qt as SCENE_DEFAULT_QUIET_SECONDS, R as FailureCounters, Rn as gifDeriveSpeed, Rr as customAction, Rt as NcTemplatePreviewSchema, S as CoverStateSchema, Sn as audioModeOf, Sr as systemEventFilterApplies, St as NcAlarmSettingsPatchSchema, T as DETECTION_MACRO_CLASSES, Tn as cosineSimilarity$1, Tr as templateCarriesSummary, Tt as NcRuleInputSchema, U as MAX_ARCHIVED_DEBUG_NOTES, Un as isKnownTemplateVar, Ut as RECORDING_EXPORT_MAX_READ_BYTES, V as ListTrackRelationsResultSchema, Vn as isDetectionMacroClass, Vr as isDeviceScopedCap, Vt as OpsLogEntrySchema, W as MAX_BIRTH_DECISION_RECORDS, Wn as isMediaOwnerType, Wr as sleep$1, Wt as RECORDING_SOURCE_CAMSTACK_ADDON, X as MotionTriggeredBySchema, Xn as kebabToCamel, Xr as literal, Xt as SCENE_DEFAULT_CHECK_INTERVAL_SEC, Y as MediaFileKindEnum, Yn as isVectorIndexDimConflict, Yr as discriminatedUnion, Yt as SCENE_DEFAULT_ANCHOR_THRESHOLD, Z as NC_ALARM_DELAY_FIELDS, Zn as mayWriteToLocation, Zr as looseObject, Zt as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, _ as BaseDevice, _n as alarmPanelCapability, _r as servedTemplateVars, _t as NC_TAXONOMY, a as CLIP_EMBEDDING_STEP_ID, ai as tuple, an as SetTrackRelationInputSchema, ar as readMotionTriggeredBy, at as NC_CLIP_RETENTION_MAX_SEC, b as ClearTrackRelationInputSchema, bn as assertTimelapseCadences, br as systemEventDeliveryProblems, bt as NcAlarmSensorsInputSchema, c as resolveClusterModelPin, ci as EventCategory, cn as TimelapseRuleInputSchema, cr as resolveLocationMode, ct as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, d as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, dn as TrackPuritySchema, dr as ruleBelongsToAlarm$1, dt as NC_GROUPING_MAX_SEC, ei as partialRecord, en as SCENE_DIVERGED, er as occupancyScope, et as NC_ALARM_TRIGGERED_MAX_SEC, f as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, fn as TrackRelationKindSchema, fr as ruleDeviceCompatCapQueries, ft as NC_GROUPING_MIN_SEC, g as BIRTH_DECISION_DEFAULT_LIMIT, gn as addonWidgetsSourceCapability, gr as sensorRaisedOf, gt as NC_TANK_SYSTEM_EVENT_KINDS, h as ArchivedDebugNoteSchema, hn as TrackSourceSchema, hr as sceneMonitorCapability, ht as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, ii as templateLiteral, in as SetTrackPurityResultSchema, ir as readDeviceStateFrom, it as NC_CLIP_PRE_ROLL_DEFAULT_SEC, j as EMBEDDING_REQUIREMENTS_UNAVAILABLE, jn as embeddingRefusalOf, jr as evaluateSensorEdge, jt as NcSnoozeInputSchema, k as EMBEDDING_MODEL_FAILED, kr as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, kt as NcRuleUpdateInputSchema, l as APPEARANCE_BIN_COUNT, ln as TimelapseRulePatchSchema, lr as resolveModeDelays, lt as NC_DEFAULT_SNOOZE_MINUTES, m as AlarmArmModeSchema, mn as TrackSideSchema, mr as ruleKindOf, mt as NC_SNOOZE_MAX_MINUTES, ni as strictObject, nn as SceneMonitorSchema, nr as pipelineAnalyticsCapability, nt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, o as FACE_EMBEDDING_STEP_ID, oi as union, on as TIMELAPSE_DENSE_FLOOR_SEC, or as readTimelapseGeneratedAt, ot as NC_CONDITION_CATALOG, p as AUDIO_MACRO_LABELS, pn as TrackRelationSchema, pr as ruleGroupingApplies, pt as NC_SENSOR_TRANSITION_KINDS, q as MAX_TRACK_RELATIONS, qn as isSystemDelivery, qr as array, qt as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, ri as string, rn as SetTrackPurityInputSchema, rr as plateGalleryCapability, rt as NC_CLIP_POST_ROLL_DEFAULT_SEC, s as readClusterModelPinStrict, si as unknown, sn as TRACK_RELATIONS_DEFAULT_LIMIT, sr as resolveClipSearchMinScore, st as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, t as BUILTIN_CLIP_MODELS, ti as record, tn as SCENE_RESET_RECAPTURES, tt as NC_AUDIO_CONFIRM_HITS_DEFAULT, u as APPEARANCE_BLOCKS, un as TimelapseRuleSchema, ut as NC_GROUPING_DEFAULT_SEC, v as BirthDecisionRecordSchema, vn as applyModeDelaysEdits, vr as storageOccupancyCapability, vt as NC_TEMPLATE_VARS, w as DEFAULT_TIMELAPSE_PREVIEW_TEXT, wn as consumableLowPercentOf, wr as systemEventSummarySplitOf, wt as NcConditionsSchema, x as ClearTrackRelationResultSchema, xn as audioMetricsCapability, xr as systemEventFamilyProblems, xt as NcAlarmSensorsSchema, y as COCO_TO_MACRO, yn as applyNonBlockingEdit, yr as subKindsOf, yt as NcAlarmConfigSchema, z as LabelAttributionSchema, zn as gifFromMp4Args, zr as defineCustomActions, zt as NcTemplateVarDescriptorSchema } from "../clip-model-registry-DSqobJfx.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";
|
|
@@ -51320,6 +51320,11 @@ var MEDIA_ID_SEGMENT = "m";
|
|
|
51320
51320
|
/** Path segment that introduces an OWNER question ("best media of"). */
|
|
51321
51321
|
var MEDIA_OWNER_SEGMENT = "o";
|
|
51322
51322
|
/**
|
|
51323
|
+
* Path segment that introduces an event-owner GENERATION (D694) —
|
|
51324
|
+
* `/g/<deviceId>/<recordAt>` after the owner id.
|
|
51325
|
+
*/
|
|
51326
|
+
var MEDIA_GENERATION_SEGMENT = "g";
|
|
51327
|
+
/**
|
|
51323
51328
|
* The plane path for one media row.
|
|
51324
51329
|
*
|
|
51325
51330
|
* `prefix` is `/addon/<addonId>/event-media` — a pure function of the addon
|
|
@@ -51336,6 +51341,23 @@ function mediaFileUrl(prefix, mediaId) {
|
|
|
51336
51341
|
return `${prefix}/${MEDIA_ID_SEGMENT}/${mediaId}`;
|
|
51337
51342
|
}
|
|
51338
51343
|
/**
|
|
51344
|
+
* The plane path for "whatever media best represents this owner".
|
|
51345
|
+
*
|
|
51346
|
+
* The owner id IS encoded: a trackId is a UUID today but an owner id is an
|
|
51347
|
+
* arbitrary row key (the summary mosaic's is `summary-<ruleId>-<windowEndMs>`),
|
|
51348
|
+
* and one slash in it would silently re-cut the path.
|
|
51349
|
+
*
|
|
51350
|
+
* When `generation` is set and `ownerType` is an event table, the path carries
|
|
51351
|
+
* `/g/<deviceId>/<recordAt>` so a reused rowid cannot resolve another record's
|
|
51352
|
+
* crop. Generation is ignored (and not minted) for non-event owners — a track
|
|
51353
|
+
* id is random and needs none.
|
|
51354
|
+
*/
|
|
51355
|
+
function mediaOwnerUrl(prefix, ownerType, ownerId, generation) {
|
|
51356
|
+
const base = `${prefix}/${MEDIA_OWNER_SEGMENT}/${ownerType}/${encodeURIComponent(ownerId)}`;
|
|
51357
|
+
if (generation === void 0 || !isEventOwnerType(ownerType)) return base;
|
|
51358
|
+
return `${base}/${MEDIA_GENERATION_SEGMENT}/${generation.deviceId}/${generation.recordAt}`;
|
|
51359
|
+
}
|
|
51360
|
+
/**
|
|
51339
51361
|
* A stored row as the wire sees it: the ref, the address, and — transitionally
|
|
51340
51362
|
* — the bytes.
|
|
51341
51363
|
*
|
|
@@ -59186,6 +59208,12 @@ function openGzipStream(out) {
|
|
|
59186
59208
|
onceDrain: (listener) => {
|
|
59187
59209
|
gzip.once("drain", listener);
|
|
59188
59210
|
},
|
|
59211
|
+
flush: () => new Promise((resolve, reject) => {
|
|
59212
|
+
gzip.flush((err) => {
|
|
59213
|
+
if (err !== null && err !== void 0) reject(err);
|
|
59214
|
+
else resolve();
|
|
59215
|
+
});
|
|
59216
|
+
}),
|
|
59189
59217
|
finish: async () => {
|
|
59190
59218
|
gzip.end();
|
|
59191
59219
|
await closed;
|
|
@@ -59281,6 +59309,25 @@ var TapeSegmentWriter = class {
|
|
|
59281
59309
|
});
|
|
59282
59310
|
}
|
|
59283
59311
|
/**
|
|
59312
|
+
* Push the sink's pending gzip output to disk without ending the segment.
|
|
59313
|
+
* A quiet / silent camera otherwise keeps its tail only in the zlib
|
|
59314
|
+
* buffer until the next rotation (D681 follow-up). Never throws into the
|
|
59315
|
+
* caller's frame path: a flush fault is logged and swallowed here.
|
|
59316
|
+
*/
|
|
59317
|
+
async flushToDisk() {
|
|
59318
|
+
try {
|
|
59319
|
+
await this.deps.sink.flush();
|
|
59320
|
+
} catch (err) {
|
|
59321
|
+
this.deps.logger.warn("tracking tape segment flush failed", {
|
|
59322
|
+
tags: { deviceId: this.deps.deviceId },
|
|
59323
|
+
meta: {
|
|
59324
|
+
segmentOriginMs: this.deps.segmentOriginMs,
|
|
59325
|
+
error: errMsg(err)
|
|
59326
|
+
}
|
|
59327
|
+
});
|
|
59328
|
+
}
|
|
59329
|
+
}
|
|
59330
|
+
/**
|
|
59284
59331
|
* Always ends the segment's records (queue flush, lost-span gap, `end`
|
|
59285
59332
|
* record) before touching the sink, so a sink that cannot finish still
|
|
59286
59333
|
* leaves a decodable body behind it. `sink.finish()`'s rejection is caught
|
|
@@ -59607,6 +59654,21 @@ var TapeRecorder = class {
|
|
|
59607
59654
|
if (cam !== void 0) await this.closeSegment(deviceId, cam, "segment-end");
|
|
59608
59655
|
}
|
|
59609
59656
|
/**
|
|
59657
|
+
* Push every open segment's pending gzip output to disk without rotating
|
|
59658
|
+
* (D681 follow-up). A silent / quiet camera otherwise keeps its tail only
|
|
59659
|
+
* in the zlib buffer until the next frame or the 10-minute cut — a crash
|
|
59660
|
+
* loses it, and `bytesLastHour` lags behind what was already recorded.
|
|
59661
|
+
* Never throws: a per-camera flush fault is logged inside the writer.
|
|
59662
|
+
*/
|
|
59663
|
+
async flushOpenSegments() {
|
|
59664
|
+
const pending = [];
|
|
59665
|
+
for (const cam of this.cameras.values()) {
|
|
59666
|
+
const writer = cam.segment?.writer;
|
|
59667
|
+
if (writer !== void 0 && writer !== null) pending.push(writer.flushToDisk());
|
|
59668
|
+
}
|
|
59669
|
+
await Promise.all(pending);
|
|
59670
|
+
}
|
|
59671
|
+
/**
|
|
59610
59672
|
* Close the camera's open segment only if it holds time at or before
|
|
59611
59673
|
* `atMs` — what a promotion of a window ending at `atMs` needs on disk
|
|
59612
59674
|
* (Task 12 fix round, H1). A window wholly before the open segment leaves
|
|
@@ -60106,6 +60168,29 @@ var TapeShelf = class {
|
|
|
60106
60168
|
};
|
|
60107
60169
|
}
|
|
60108
60170
|
};
|
|
60171
|
+
/**
|
|
60172
|
+
* Log every refusal the sweep already measured (D391 / D681 follow-up).
|
|
60173
|
+
* `sweep()` itself never throws for `rootUnreadable` / per-camera `failed`:
|
|
60174
|
+
* those land on the report, and a caller that only `.catch`es would drop them
|
|
60175
|
+
* silently even when the shelf already warned at the `readdir` site. One
|
|
60176
|
+
* tagged line per refusal at the sweep boundary closes that gap.
|
|
60177
|
+
*/
|
|
60178
|
+
function logTapeSweepReport(report, logger) {
|
|
60179
|
+
if (report.rootUnreadable !== null) logger.warn("tracking tape sweep refused", { meta: {
|
|
60180
|
+
reason: report.rootUnreadable,
|
|
60181
|
+
scope: "root"
|
|
60182
|
+
} });
|
|
60183
|
+
for (const [deviceId, outcome] of report.perDevice) {
|
|
60184
|
+
if (!("failed" in outcome) || outcome.failed !== true) continue;
|
|
60185
|
+
logger.warn("tracking tape sweep refused", {
|
|
60186
|
+
tags: { deviceId },
|
|
60187
|
+
meta: {
|
|
60188
|
+
reason: outcome.reason,
|
|
60189
|
+
scope: "camera"
|
|
60190
|
+
}
|
|
60191
|
+
});
|
|
60192
|
+
}
|
|
60193
|
+
}
|
|
60109
60194
|
//#endregion
|
|
60110
60195
|
//#region src/pipeline-analytics/tracking-bench/recorder/tape-operation-queue.ts
|
|
60111
60196
|
/** Generous: a promotion reads its window's segments and walks back through
|
|
@@ -61159,6 +61244,17 @@ function shelfFigures(listing, now) {
|
|
|
61159
61244
|
...last !== void 0 ? { heldToMs: last.originMs } : {}
|
|
61160
61245
|
};
|
|
61161
61246
|
}
|
|
61247
|
+
/**
|
|
61248
|
+
* Default `debug.tape.status` (no `deviceIds`): drop the noise. An Off camera
|
|
61249
|
+
* with a measured empty shelf is not a cost row and is not promotable; keep
|
|
61250
|
+
* everything else — Recording / Refused / Failing / Unknown, Off with held
|
|
61251
|
+
* segments (still promotable after the switch went off), and Off whose shelf
|
|
61252
|
+
* could not be read (D393: never silently hide an unreadable camera). Explicit
|
|
61253
|
+
* `deviceIds` still return every asked-about camera, Off included (D62).
|
|
61254
|
+
*/
|
|
61255
|
+
function defaultTapeStatusCameras(rows) {
|
|
61256
|
+
return rows.filter((row) => row.state !== "off" || row.segmentsHeld === null || row.segmentsHeld > 0);
|
|
61257
|
+
}
|
|
61162
61258
|
function describeTapeStatus(input) {
|
|
61163
61259
|
return input.deviceIds.map((deviceId) => {
|
|
61164
61260
|
const shelf = {
|
|
@@ -73017,7 +73113,7 @@ var AnalyticsQueryFacade = class {
|
|
|
73017
73113
|
async getMotionEvents(input) {
|
|
73018
73114
|
const events = await (this.deps.eventStore()?.queryMotion(input) ?? Promise.resolve([]));
|
|
73019
73115
|
if (input.projection !== "slim" || this.deps.eventMediaBaseUrl() === null) return events;
|
|
73020
|
-
return this.withMediaUrl(events);
|
|
73116
|
+
return this.withMediaUrl(events, "motion");
|
|
73021
73117
|
}
|
|
73022
73118
|
async getEventDensity(input) {
|
|
73023
73119
|
return this.deps.eventStore()?.densityByKind(input) ?? [];
|
|
@@ -73074,12 +73170,12 @@ var AnalyticsQueryFacade = class {
|
|
|
73074
73170
|
async getObjectEvents(input) {
|
|
73075
73171
|
const events = await (this.deps.eventStore()?.queryObject(input) ?? Promise.resolve([]));
|
|
73076
73172
|
if (input.projection !== "slim" || this.deps.eventMediaBaseUrl() === null) return events;
|
|
73077
|
-
return this.withMediaUrl(events);
|
|
73173
|
+
return this.withMediaUrl(events, "object");
|
|
73078
73174
|
}
|
|
73079
73175
|
async getAudioEvents(input) {
|
|
73080
73176
|
const events = await (this.deps.eventStore()?.queryAudio(input) ?? Promise.resolve([]));
|
|
73081
73177
|
if (input.projection !== "slim" || this.deps.eventMediaBaseUrl() === null) return events;
|
|
73082
|
-
return this.withMediaUrl(events);
|
|
73178
|
+
return this.withMediaUrl(events, "audio");
|
|
73083
73179
|
}
|
|
73084
73180
|
async getEventMedia(input) {
|
|
73085
73181
|
const store = this.deps.mediaStore();
|
|
@@ -73346,13 +73442,20 @@ var AnalyticsQueryFacade = class {
|
|
|
73346
73442
|
*
|
|
73347
73443
|
* Only called when `eventMediaBaseUrl()` is non-null (guard sits in
|
|
73348
73444
|
* the callers), so the template literal is safe.
|
|
73445
|
+
*
|
|
73446
|
+
* The URL names the owner TABLE and the event's GENERATION (D482 + D694):
|
|
73447
|
+
* a bare `${base}/${id}` was both ambiguous across tables and unable to
|
|
73448
|
+
* survive a reused rowid. New stamps always carry `/o/<type>/<id>/g/…`.
|
|
73349
73449
|
*/
|
|
73350
|
-
withMediaUrl(events) {
|
|
73450
|
+
withMediaUrl(events, ownerType) {
|
|
73351
73451
|
const base = this.deps.eventMediaBaseUrl();
|
|
73352
73452
|
if (base === null) return events;
|
|
73353
73453
|
return events.map((e) => ({
|
|
73354
73454
|
...e,
|
|
73355
|
-
mediaUrl:
|
|
73455
|
+
mediaUrl: mediaOwnerUrl(base, ownerType, String(e.id), {
|
|
73456
|
+
deviceId: e.deviceId,
|
|
73457
|
+
recordAt: e.timestamp
|
|
73458
|
+
})
|
|
73356
73459
|
}));
|
|
73357
73460
|
}
|
|
73358
73461
|
};
|
|
@@ -76184,18 +76287,26 @@ function eventMediaEtag(media) {
|
|
|
76184
76287
|
}
|
|
76185
76288
|
/** Digits only — `Number('')` is 0 and `Number(' ')` is 0, so neither is used. */
|
|
76186
76289
|
var DIGITS = /^\d+$/;
|
|
76290
|
+
/** One run of digits, for composing the event-owner remainder pattern. */
|
|
76291
|
+
var DIGIT_RUN = "\\d+";
|
|
76292
|
+
/**
|
|
76293
|
+
* Event-owner remainder with an optional generation suffix (D694):
|
|
76294
|
+
* `<ownerId>` or `<ownerId>/g/<deviceId>/<recordAt>`. Owner ids for event
|
|
76295
|
+
* tables are decimal rowids; the generation segment is the literal `g`.
|
|
76296
|
+
*/
|
|
76297
|
+
var EVENT_OWNER_REMAINDER = new RegExp(`^(${DIGIT_RUN})(?:/${MEDIA_GENERATION_SEGMENT}/(${DIGIT_RUN})/(${DIGIT_RUN}))?$`);
|
|
76187
76298
|
/**
|
|
76188
76299
|
* Read a plane path. `null` for anything that is not one of the two forms —
|
|
76189
76300
|
* including the BARE id the plane used to accept, which is gone: a bare number
|
|
76190
76301
|
* could be a media id or an event id, and after D474 an event id could be one
|
|
76191
76302
|
* of three rows. Ambiguity at the door is what this record removes.
|
|
76192
76303
|
*
|
|
76193
|
-
*
|
|
76194
|
-
* hub's wildcard param is percent-decoded by find-my-way before the
|
|
76195
|
-
* is proxied, so a `%2F` an owner id carried would arrive here as a
|
|
76196
|
-
* slash, and re-cutting on it would silently address a different owner.
|
|
76197
|
-
*
|
|
76198
|
-
*
|
|
76304
|
+
* For non-event owners the id is the whole remainder rather than one segment:
|
|
76305
|
+
* the hub's wildcard param is percent-decoded by find-my-way before the
|
|
76306
|
+
* sub-path is proxied, so a `%2F` an owner id carried would arrive here as a
|
|
76307
|
+
* real slash, and re-cutting on it would silently address a different owner.
|
|
76308
|
+
* Event owners (decimal rowids) may end with `/g/<deviceId>/<recordAt>` —
|
|
76309
|
+
* that suffix is the generation, not part of the id (D694).
|
|
76199
76310
|
*/
|
|
76200
76311
|
function parseMediaAddress(rawPath) {
|
|
76201
76312
|
const path = rawPath.replace(/^\/+/, "");
|
|
@@ -76215,13 +76326,35 @@ function parseMediaAddress(rawPath) {
|
|
|
76215
76326
|
const typeSlash = rest.indexOf("/");
|
|
76216
76327
|
if (typeSlash <= 0) return null;
|
|
76217
76328
|
const ownerType = rest.slice(0, typeSlash);
|
|
76218
|
-
const
|
|
76219
|
-
if (
|
|
76329
|
+
const remainder = rest.slice(typeSlash + 1);
|
|
76330
|
+
if (remainder.length === 0) return null;
|
|
76220
76331
|
if (!isMediaOwnerType(ownerType)) return null;
|
|
76332
|
+
if (isEventOwnerType(ownerType)) {
|
|
76333
|
+
const match = EVENT_OWNER_REMAINDER.exec(remainder);
|
|
76334
|
+
if (match === null) return null;
|
|
76335
|
+
const ownerId = match[1];
|
|
76336
|
+
const deviceIdRaw = match[2];
|
|
76337
|
+
const recordAtRaw = match[3];
|
|
76338
|
+
if (ownerId === void 0) return null;
|
|
76339
|
+
if (deviceIdRaw !== void 0 && recordAtRaw !== void 0) return {
|
|
76340
|
+
kind: "owner",
|
|
76341
|
+
ownerType,
|
|
76342
|
+
ownerId,
|
|
76343
|
+
generation: {
|
|
76344
|
+
deviceId: Number(deviceIdRaw),
|
|
76345
|
+
recordAt: Number(recordAtRaw)
|
|
76346
|
+
}
|
|
76347
|
+
};
|
|
76348
|
+
return {
|
|
76349
|
+
kind: "owner",
|
|
76350
|
+
ownerType,
|
|
76351
|
+
ownerId
|
|
76352
|
+
};
|
|
76353
|
+
}
|
|
76221
76354
|
return {
|
|
76222
76355
|
kind: "owner",
|
|
76223
76356
|
ownerType,
|
|
76224
|
-
ownerId
|
|
76357
|
+
ownerId: remainder
|
|
76225
76358
|
};
|
|
76226
76359
|
}
|
|
76227
76360
|
/** Set by the HUB for a `csv_*` share token admitted on this plane; never by a client. */
|
|
@@ -78898,6 +79031,218 @@ function createRetrainExportHandler(deps) {
|
|
|
78898
79031
|
};
|
|
78899
79032
|
}
|
|
78900
79033
|
//#endregion
|
|
79034
|
+
//#region src/pipeline-analytics/retrain/retrain-collection-store.ts
|
|
79035
|
+
/**
|
|
79036
|
+
* @durable class=ledger owner=pipeline-analytics
|
|
79037
|
+
* write="one row per named training collection the operator creates. Names are
|
|
79038
|
+
* unique on nameKey (lower(trim)); empty names never become rows."
|
|
79039
|
+
* retention="none — operator-owned corpus metadata. Rows leave only when an
|
|
79040
|
+
* explicit delete API lands (not V1)."
|
|
79041
|
+
*/
|
|
79042
|
+
var RETRAIN_COLLECTIONS_COLLECTION = "pipeline-analytics:retrain-collections";
|
|
79043
|
+
var RETRAIN_COLLECTION_COLUMNS = [
|
|
79044
|
+
{
|
|
79045
|
+
name: "id",
|
|
79046
|
+
type: "TEXT",
|
|
79047
|
+
primaryKey: true,
|
|
79048
|
+
notNull: true
|
|
79049
|
+
},
|
|
79050
|
+
{
|
|
79051
|
+
name: "name",
|
|
79052
|
+
type: "TEXT",
|
|
79053
|
+
notNull: true
|
|
79054
|
+
},
|
|
79055
|
+
{
|
|
79056
|
+
name: "nameKey",
|
|
79057
|
+
type: "TEXT",
|
|
79058
|
+
notNull: true
|
|
79059
|
+
},
|
|
79060
|
+
{
|
|
79061
|
+
name: "createdAt",
|
|
79062
|
+
type: "INTEGER",
|
|
79063
|
+
notNull: true
|
|
79064
|
+
},
|
|
79065
|
+
{
|
|
79066
|
+
name: "updatedAt",
|
|
79067
|
+
type: "INTEGER",
|
|
79068
|
+
notNull: true
|
|
79069
|
+
}
|
|
79070
|
+
];
|
|
79071
|
+
var RETRAIN_COLLECTION_INDEXES = [{
|
|
79072
|
+
name: "idx_retrain_collections_name_key",
|
|
79073
|
+
columns: ["nameKey"],
|
|
79074
|
+
unique: true
|
|
79075
|
+
}, {
|
|
79076
|
+
name: "idx_retrain_collections_created",
|
|
79077
|
+
columns: ["createdAt"]
|
|
79078
|
+
}];
|
|
79079
|
+
function normalizeCollectionName(raw) {
|
|
79080
|
+
const name = raw.trim();
|
|
79081
|
+
if (name.length === 0) return null;
|
|
79082
|
+
return {
|
|
79083
|
+
name,
|
|
79084
|
+
nameKey: name.toLowerCase()
|
|
79085
|
+
};
|
|
79086
|
+
}
|
|
79087
|
+
var RetrainCollectionStore = class {
|
|
79088
|
+
store;
|
|
79089
|
+
logger;
|
|
79090
|
+
now;
|
|
79091
|
+
newId;
|
|
79092
|
+
countFrames;
|
|
79093
|
+
constructor(deps) {
|
|
79094
|
+
this.store = deps.store;
|
|
79095
|
+
this.logger = deps.logger;
|
|
79096
|
+
this.now = deps.now;
|
|
79097
|
+
this.newId = deps.newId;
|
|
79098
|
+
this.countFrames = deps.countFrames;
|
|
79099
|
+
}
|
|
79100
|
+
static async declare(store) {
|
|
79101
|
+
await store.declareCollection.mutate({
|
|
79102
|
+
collection: RETRAIN_COLLECTIONS_COLLECTION,
|
|
79103
|
+
columns: [...RETRAIN_COLLECTION_COLUMNS],
|
|
79104
|
+
indexes: [...RETRAIN_COLLECTION_INDEXES]
|
|
79105
|
+
});
|
|
79106
|
+
}
|
|
79107
|
+
async create(input) {
|
|
79108
|
+
const normalized = normalizeCollectionName(input.name);
|
|
79109
|
+
if (normalized === null) return {
|
|
79110
|
+
kind: "refused",
|
|
79111
|
+
reason: "empty-name"
|
|
79112
|
+
};
|
|
79113
|
+
if (await this.findByNameKey(normalized.nameKey) !== null) return {
|
|
79114
|
+
kind: "refused",
|
|
79115
|
+
reason: "duplicate-name"
|
|
79116
|
+
};
|
|
79117
|
+
const createdAt = this.now();
|
|
79118
|
+
const id = this.newId();
|
|
79119
|
+
await this.store.set.mutate({
|
|
79120
|
+
collection: RETRAIN_COLLECTIONS_COLLECTION,
|
|
79121
|
+
key: id,
|
|
79122
|
+
value: {
|
|
79123
|
+
name: normalized.name,
|
|
79124
|
+
nameKey: normalized.nameKey,
|
|
79125
|
+
createdAt,
|
|
79126
|
+
updatedAt: createdAt
|
|
79127
|
+
}
|
|
79128
|
+
});
|
|
79129
|
+
return {
|
|
79130
|
+
kind: "created",
|
|
79131
|
+
collection: {
|
|
79132
|
+
id,
|
|
79133
|
+
name: normalized.name,
|
|
79134
|
+
createdAt,
|
|
79135
|
+
frameCount: 0
|
|
79136
|
+
}
|
|
79137
|
+
};
|
|
79138
|
+
}
|
|
79139
|
+
async list() {
|
|
79140
|
+
let rows;
|
|
79141
|
+
try {
|
|
79142
|
+
rows = await this.store.query.query({
|
|
79143
|
+
collection: RETRAIN_COLLECTIONS_COLLECTION,
|
|
79144
|
+
filter: { orderBy: {
|
|
79145
|
+
field: "createdAt",
|
|
79146
|
+
direction: "desc"
|
|
79147
|
+
} }
|
|
79148
|
+
});
|
|
79149
|
+
} catch (err) {
|
|
79150
|
+
this.logger.warn("retrain collections list failed", { meta: { error: String(err) } });
|
|
79151
|
+
return [];
|
|
79152
|
+
}
|
|
79153
|
+
const out = [];
|
|
79154
|
+
for (const row of rows) {
|
|
79155
|
+
const name = typeof row.data["name"] === "string" ? row.data["name"] : "";
|
|
79156
|
+
const createdAt = Number(row.data["createdAt"] ?? 0);
|
|
79157
|
+
const frameCount = this.countFrames !== void 0 ? await this.countFrames(row.id) : 0;
|
|
79158
|
+
out.push({
|
|
79159
|
+
id: row.id,
|
|
79160
|
+
name,
|
|
79161
|
+
createdAt,
|
|
79162
|
+
frameCount
|
|
79163
|
+
});
|
|
79164
|
+
}
|
|
79165
|
+
return out;
|
|
79166
|
+
}
|
|
79167
|
+
async getById(id) {
|
|
79168
|
+
try {
|
|
79169
|
+
const row = await this.store.get.query({
|
|
79170
|
+
collection: RETRAIN_COLLECTIONS_COLLECTION,
|
|
79171
|
+
key: id
|
|
79172
|
+
});
|
|
79173
|
+
if (row === null || row === void 0) return null;
|
|
79174
|
+
const data = row;
|
|
79175
|
+
return {
|
|
79176
|
+
id,
|
|
79177
|
+
name: typeof data["name"] === "string" ? data["name"] : "",
|
|
79178
|
+
createdAt: Number(data["createdAt"] ?? 0),
|
|
79179
|
+
frameCount: this.countFrames !== void 0 ? await this.countFrames(id) : 0
|
|
79180
|
+
};
|
|
79181
|
+
} catch (err) {
|
|
79182
|
+
this.logger.warn("retrain collection get failed", { meta: {
|
|
79183
|
+
collectionId: id,
|
|
79184
|
+
error: String(err)
|
|
79185
|
+
} });
|
|
79186
|
+
return null;
|
|
79187
|
+
}
|
|
79188
|
+
}
|
|
79189
|
+
/**
|
|
79190
|
+
* Stub until still ingest lands. Validates the collection exists, then
|
|
79191
|
+
* refuses with a named reason so callers can wire UI against a stable shape.
|
|
79192
|
+
*/
|
|
79193
|
+
async addRetrainFrameFromRecording(input) {
|
|
79194
|
+
if (await this.getById(input.collectionId) === null) {
|
|
79195
|
+
this.logger.info("retrain collection addFrame refused: unknown-collection", {
|
|
79196
|
+
tags: { deviceId: input.deviceId },
|
|
79197
|
+
meta: {
|
|
79198
|
+
collectionId: input.collectionId,
|
|
79199
|
+
epochMs: input.epochMs
|
|
79200
|
+
}
|
|
79201
|
+
});
|
|
79202
|
+
return {
|
|
79203
|
+
kind: "refused",
|
|
79204
|
+
reason: "unknown-collection"
|
|
79205
|
+
};
|
|
79206
|
+
}
|
|
79207
|
+
this.logger.info("retrain collection addFrame stub: still-capture-unimplemented", {
|
|
79208
|
+
tags: { deviceId: input.deviceId },
|
|
79209
|
+
meta: {
|
|
79210
|
+
collectionId: input.collectionId,
|
|
79211
|
+
epochMs: input.epochMs
|
|
79212
|
+
}
|
|
79213
|
+
});
|
|
79214
|
+
return {
|
|
79215
|
+
kind: "refused",
|
|
79216
|
+
reason: "still-capture-unimplemented",
|
|
79217
|
+
detail: "Still ingest lands in plan Task 3"
|
|
79218
|
+
};
|
|
79219
|
+
}
|
|
79220
|
+
async findByNameKey(nameKey) {
|
|
79221
|
+
try {
|
|
79222
|
+
const row = (await this.store.query.query({
|
|
79223
|
+
collection: RETRAIN_COLLECTIONS_COLLECTION,
|
|
79224
|
+
filter: {
|
|
79225
|
+
where: { nameKey },
|
|
79226
|
+
limit: 1
|
|
79227
|
+
}
|
|
79228
|
+
}))[0];
|
|
79229
|
+
if (row === void 0) return null;
|
|
79230
|
+
return {
|
|
79231
|
+
id: row.id,
|
|
79232
|
+
name: typeof row.data["name"] === "string" ? row.data["name"] : "",
|
|
79233
|
+
createdAt: Number(row.data["createdAt"] ?? 0),
|
|
79234
|
+
frameCount: 0
|
|
79235
|
+
};
|
|
79236
|
+
} catch (err) {
|
|
79237
|
+
this.logger.warn("retrain collection findByNameKey failed", { meta: {
|
|
79238
|
+
nameKey,
|
|
79239
|
+
error: String(err)
|
|
79240
|
+
} });
|
|
79241
|
+
return null;
|
|
79242
|
+
}
|
|
79243
|
+
}
|
|
79244
|
+
};
|
|
79245
|
+
//#endregion
|
|
78901
79246
|
//#region src/pipeline-analytics/retrain/retrain-assist.ts
|
|
78902
79247
|
/** The whole frame, as a normalised rectangle. */
|
|
78903
79248
|
var WHOLE_FRAME = {
|
|
@@ -82307,7 +82652,8 @@ async function rankKeyEvents(candidates, options, peakLookup) {
|
|
|
82307
82652
|
...t.markForTrain !== void 0 ? { markForTrain: t.markForTrain } : {},
|
|
82308
82653
|
...t.retrainStatus !== void 0 ? { retrainStatus: t.retrainStatus } : {},
|
|
82309
82654
|
...t.debug !== void 0 ? { debug: t.debug } : {},
|
|
82310
|
-
...t.favourited !== void 0 ? { favourited: t.favourited } : {}
|
|
82655
|
+
...t.favourited !== void 0 ? { favourited: t.favourited } : {},
|
|
82656
|
+
...t.audioLabels !== void 0 && t.audioLabels.length > 0 ? { audioLabels: t.audioLabels } : {}
|
|
82311
82657
|
});
|
|
82312
82658
|
}
|
|
82313
82659
|
scored.sort((a, b) => b.importance - a.importance);
|
|
@@ -82734,16 +83080,19 @@ var MotionOnsetRegistry = class {
|
|
|
82734
83080
|
* - `resolveSearchThumbnailUrl` — the search-hit thumbnail resolver. It points
|
|
82735
83081
|
* a hit at the CLIP embedding row's OWN crop (the crop captured on the
|
|
82736
83082
|
* embedding's peak frame → the hit thumbnail IS the embedded crop), and only
|
|
82737
|
-
* falls back to the representative event's
|
|
82738
|
-
* crop yet, so a hit never renders blank.
|
|
83083
|
+
* falls back to the representative event's owner ladder when the embedding
|
|
83084
|
+
* row has no crop yet, so a hit never renders blank.
|
|
82739
83085
|
*/
|
|
82740
83086
|
function isClipObjectEmbedding(t, registry = BUILTIN_CLIP_MODELS) {
|
|
82741
83087
|
return Array.isArray(t.embedding) && t.embedding.length > 0 && typeof t.embeddingModelId === "string" && registry.resolve(t.embeddingModelId) !== null;
|
|
82742
83088
|
}
|
|
82743
83089
|
function resolveSearchThumbnailUrl(input) {
|
|
82744
83090
|
if (input.baseUrl === null) return void 0;
|
|
82745
|
-
|
|
82746
|
-
return
|
|
83091
|
+
if (input.embeddingMediaId !== void 0) return mediaFileUrl(input.baseUrl, input.embeddingMediaId);
|
|
83092
|
+
return mediaOwnerUrl(input.baseUrl, "object", input.eventId, {
|
|
83093
|
+
deviceId: input.deviceId,
|
|
83094
|
+
recordAt: input.recordAt
|
|
83095
|
+
});
|
|
82747
83096
|
}
|
|
82748
83097
|
//#endregion
|
|
82749
83098
|
//#region src/pipeline-analytics/pipeline/onboard-birth-authority.ts
|
|
@@ -100903,7 +101252,10 @@ function ofGeneration(files, scope) {
|
|
|
100903
101252
|
function makeNcOwnerMediaReader(deps) {
|
|
100904
101253
|
return async (ownerKind, ownerId, eventScope) => {
|
|
100905
101254
|
if (ownerKind === "track") return deps.media.listByOwner("track", await deps.resolveTrackOwnerId(ownerId));
|
|
100906
|
-
if (eventScope === void 0)
|
|
101255
|
+
if (eventScope === void 0) {
|
|
101256
|
+
deps.logger.error("object media read refused — NcEventMediaScope required", { meta: { ownerId } });
|
|
101257
|
+
return [];
|
|
101258
|
+
}
|
|
100907
101259
|
const onCamera = await deps.media.listByOwner("object", ownerId, eventScope.deviceId);
|
|
100908
101260
|
const kept = ofGeneration(onCamera, eventScope);
|
|
100909
101261
|
if (kept.length < onCamera.length) deps.logger.warn("event media of another record on a reused event id — not used", {
|
|
@@ -101996,6 +102348,10 @@ var NC_ARTIFACT_PRUNE_INTERVAL_MS = 36e5;
|
|
|
101996
102348
|
* (every camera switched off): the bound is 24 h, not "24 h after the next
|
|
101997
102349
|
* close" (D681). */
|
|
101998
102350
|
var TAPE_SWEEP_INTERVAL_MS = 36e5;
|
|
102351
|
+
/** How often open tape segments push their pending gzip output to disk
|
|
102352
|
+
* without rotating (D681 follow-up): a silent camera otherwise keeps its
|
|
102353
|
+
* tail only in the zlib buffer until the next frame or the 10-minute cut. */
|
|
102354
|
+
var TAPE_FLUSH_INTERVAL_MS = 6e4;
|
|
101999
102355
|
/** What a publish answers on a node whose artifact plane never came up: no
|
|
102000
102356
|
* link, no index row — and, exactly as before, bytes-only delivery. */
|
|
102001
102357
|
var NO_PUBLICATION = {
|
|
@@ -102529,6 +102885,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
102529
102885
|
ncArtifactReadDataPlane = null;
|
|
102530
102886
|
ncArtifactPruneTimer = null;
|
|
102531
102887
|
tapeSweepTimer = null;
|
|
102888
|
+
tapeFlushTimer = null;
|
|
102532
102889
|
/** Why `startTrackingTapes` threw on a node that was allowed to record —
|
|
102533
102890
|
* reported `failing` per switched-on camera, never as `recording`. */
|
|
102534
102891
|
tapeStartFailure = null;
|
|
@@ -104333,6 +104690,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
104333
104690
|
StationaryObjectRegistry.declare(api.settingsStore),
|
|
104334
104691
|
RetrainFrameStore.declare(api.settingsStore),
|
|
104335
104692
|
RetrainAnnotationStore.declare(api.settingsStore),
|
|
104693
|
+
RetrainCollectionStore.declare(api.settingsStore),
|
|
104336
104694
|
OpsLogStore.declare(api.settingsStore),
|
|
104337
104695
|
DebugNoteArchiveStore.declare(api.settingsStore),
|
|
104338
104696
|
TrackingTapeIndexStore.declare(api.settingsStore),
|
|
@@ -106781,6 +107139,10 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
106781
107139
|
clearInterval(this.tapeSweepTimer);
|
|
106782
107140
|
this.tapeSweepTimer = null;
|
|
106783
107141
|
}
|
|
107142
|
+
if (this.tapeFlushTimer !== null) {
|
|
107143
|
+
clearInterval(this.tapeFlushTimer);
|
|
107144
|
+
this.tapeFlushTimer = null;
|
|
107145
|
+
}
|
|
106784
107146
|
if (this.ncArtifactPruneTimer !== null) {
|
|
106785
107147
|
clearInterval(this.ncArtifactPruneTimer);
|
|
106786
107148
|
this.ncArtifactPruneTimer = null;
|
|
@@ -113554,10 +113916,13 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
113554
113916
|
});
|
|
113555
113917
|
const scored = [];
|
|
113556
113918
|
for (const { event, score } of bestEventByTrackId.values()) {
|
|
113919
|
+
const embeddingMediaId = event.trackId !== void 0 ? embeddingMediaIdByTrackId.get(event.trackId) : void 0;
|
|
113557
113920
|
const mediaUrl = resolveSearchThumbnailUrl({
|
|
113558
113921
|
baseUrl: this.eventMediaBaseUrl,
|
|
113559
113922
|
eventId: String(event.id),
|
|
113560
|
-
|
|
113923
|
+
deviceId: event.deviceId,
|
|
113924
|
+
recordAt: event.timestamp,
|
|
113925
|
+
...embeddingMediaId !== void 0 ? { embeddingMediaId } : {}
|
|
113561
113926
|
});
|
|
113562
113927
|
const keyFrameMediaId = event.trackId !== void 0 ? keyFrameMediaIdByTrackId.get(event.trackId) : void 0;
|
|
113563
113928
|
scored.push({
|
|
@@ -113944,7 +114309,9 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
113944
114309
|
logger
|
|
113945
114310
|
});
|
|
113946
114311
|
const sweep = (deviceId) => {
|
|
113947
|
-
shelf.sweep().
|
|
114312
|
+
shelf.sweep().then((report) => {
|
|
114313
|
+
logTapeSweepReport(report, logger);
|
|
114314
|
+
}).catch((err) => {
|
|
113948
114315
|
logger.warn("tracking tape sweep failed", {
|
|
113949
114316
|
...deviceId !== null ? { tags: { deviceId } } : {},
|
|
113950
114317
|
meta: { error: errMsg(err) }
|
|
@@ -113976,6 +114343,10 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
113976
114343
|
sweep(null);
|
|
113977
114344
|
this.tapeSweepTimer = setInterval(() => sweep(null), TAPE_SWEEP_INTERVAL_MS);
|
|
113978
114345
|
this.tapeSweepTimer.unref?.();
|
|
114346
|
+
this.tapeFlushTimer = setInterval(() => {
|
|
114347
|
+
this.tapeRecorder?.flushOpenSegments();
|
|
114348
|
+
}, TAPE_FLUSH_INTERVAL_MS);
|
|
114349
|
+
this.tapeFlushTimer.unref?.();
|
|
113979
114350
|
this.ctx.logger.info("tracking tapes ready", { meta: { seededProcessors: this.processorInputs.size } });
|
|
113980
114351
|
} catch (err) {
|
|
113981
114352
|
this.tapeStartFailure = errMsg(err);
|
|
@@ -114168,7 +114539,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
114168
114539
|
segments.set(deviceId, await this.tapeListingOf(shelf, deviceId));
|
|
114169
114540
|
}
|
|
114170
114541
|
const recorder = this.tapeRecorder;
|
|
114171
|
-
|
|
114542
|
+
const cameras = describeTapeStatus({
|
|
114172
114543
|
deviceIds,
|
|
114173
114544
|
switchOn,
|
|
114174
114545
|
switchUnreadable,
|
|
@@ -114177,7 +114548,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
114177
114548
|
startFailure: this.tapeStartFailure,
|
|
114178
114549
|
segments,
|
|
114179
114550
|
now: Date.now()
|
|
114180
|
-
})
|
|
114551
|
+
});
|
|
114552
|
+
return { cameras: input.deviceIds === void 0 ? defaultTapeStatusCameras(cameras) : cameras };
|
|
114181
114553
|
},
|
|
114182
114554
|
"debug.tape.promote": async (input) => {
|
|
114183
114555
|
const deps = this.tapePromotionDeps();
|
|
@@ -114626,7 +114998,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
114626
114998
|
* owner table, so the motion/object coin-flip is gone from here too.
|
|
114627
114999
|
*/
|
|
114628
115000
|
async readMediaByAddress(address, variant, preferKind) {
|
|
114629
|
-
const base = address.kind === "row" ? await this.readMediaById(address.mediaId) : await this.readOwnerThumbnail(address.ownerType, address.ownerId, preferKind);
|
|
115001
|
+
const base = address.kind === "row" ? await this.readMediaById(address.mediaId) : await this.readOwnerThumbnail(address.ownerType, address.ownerId, preferKind, address.generation);
|
|
114630
115002
|
if (base === null || variant === void 0) return base;
|
|
114631
115003
|
return this.applyThumbVariant(base, variant);
|
|
114632
115004
|
}
|
|
@@ -114684,7 +115056,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
114684
115056
|
* ~144 MB and allocated ~190 MB of base64 to deliver ~1.2 MB, all of it on
|
|
114685
115057
|
* the single-threaded post-analysis runner.
|
|
114686
115058
|
*/
|
|
114687
|
-
async readOwnerThumbnail(ownerType, rawOwnerId, preferKind) {
|
|
115059
|
+
async readOwnerThumbnail(ownerType, rawOwnerId, preferKind, addressGeneration) {
|
|
114688
115060
|
const ownerId = ownerType === "track" ? await resolveMediaOwnerId(ownerType, rawOwnerId, (id) => this.trackAliasStore?.resolve(id) ?? Promise.resolve(null), (failure) => this.aliasResolveFailureLogger?.(failure), "readOwnerThumbnail") : rawOwnerId;
|
|
114689
115061
|
const listInfo = (ownerKind, id, deviceId) => this.mediaStore?.listInfoByOwner(ownerKind, id, deviceId) ?? Promise.resolve([]);
|
|
114690
115062
|
const getTrackIdForEvent = (eventId) => isEventOwnerType(ownerType) ? this.eventStore?.getTrackIdForEvent(eventId, ownerType) ?? Promise.resolve(null) : Promise.resolve(null);
|
|
@@ -114698,8 +115070,11 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
114698
115070
|
};
|
|
114699
115071
|
};
|
|
114700
115072
|
let ownFiles = await listInfo(ownerType, ownerId);
|
|
114701
|
-
if (isEventOwnerType(ownerType)
|
|
114702
|
-
const gen =
|
|
115073
|
+
if (isEventOwnerType(ownerType)) {
|
|
115074
|
+
const gen = addressGeneration !== void 0 ? {
|
|
115075
|
+
deviceId: addressGeneration.deviceId,
|
|
115076
|
+
timestamp: addressGeneration.recordAt
|
|
115077
|
+
} : this.eventStore !== null ? await this.eventStore.eventGenerationOf(ownerType, ownerId) : null;
|
|
114703
115078
|
if (gen !== null) {
|
|
114704
115079
|
const onCamera = await listInfo(ownerType, ownerId, gen.deviceId);
|
|
114705
115080
|
const kept = onCamera.filter((f) => f.timestamp === gen.timestamp);
|
|
@@ -114711,7 +115086,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
114711
115086
|
recordAt: gen.timestamp,
|
|
114712
115087
|
refused: onCamera.length - kept.length,
|
|
114713
115088
|
kept: kept.length,
|
|
114714
|
-
via: "readOwnerThumbnail"
|
|
115089
|
+
via: "readOwnerThumbnail",
|
|
115090
|
+
scopedBy: addressGeneration !== void 0 ? "url" : "live-row"
|
|
114715
115091
|
}
|
|
114716
115092
|
});
|
|
114717
115093
|
ownFiles = kept;
|