@camstack/addon-post-analysis 1.2.632 → 1.2.633

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.
Files changed (15) hide show
  1. package/dist/{clip-model-registry-0ayA23hb.mjs → clip-model-registry-CCbbEBYS.mjs} +472 -73
  2. package/dist/{clip-model-registry-DYX14HE-.js → clip-model-registry-CeNmplcH.js} +489 -72
  3. package/dist/embedding-encoder/index.js +1 -1
  4. package/dist/embedding-encoder/index.mjs +1 -1
  5. package/dist/pipeline-analytics/_stub.js +2 -2
  6. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-HmQ3SInG.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-ArpdWsMY.mjs} +2 -2
  7. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BQq3WNOE.mjs +26 -0
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-MOlfkem8.mjs +26 -0
  9. package/dist/pipeline-analytics/{hostInit-CP1G3VOf.mjs → hostInit-g5HpKRU7.mjs} +2 -2
  10. package/dist/pipeline-analytics/index.js +108 -17
  11. package/dist/pipeline-analytics/index.mjs +108 -17
  12. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  13. package/package.json +1 -1
  14. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BFPYidGl.mjs +0 -26
  15. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DdbV-R1z.mjs +0 -26
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_clip_model_registry = require("../clip-model-registry-DYX14HE-.js");
5
+ const require_clip_model_registry = require("../clip-model-registry-CeNmplcH.js");
6
6
  let node_fs = require("node:fs");
7
7
  node_fs = require_clip_model_registry.__toESM(node_fs, 1);
8
8
  let node_path = require("node:path");
@@ -25,6 +25,66 @@ let node_http = require("node:http");
25
25
  let node_https = require("node:https");
26
26
  let node_timers_promises = require("node:timers/promises");
27
27
  let node_buffer = require("node:buffer");
28
+ //#region src/shared/display-palette-painter.ts
29
+ var REFRESH_MS = 3e4;
30
+ function isRecord$5(value) {
31
+ return typeof value === "object" && value !== null;
32
+ }
33
+ function isPaletteQueryApi(value) {
34
+ if (!("displayPalette" in value)) return false;
35
+ const cap = value.displayPalette;
36
+ if (!isRecord$5(cap) || !("getPalette" in cap)) return false;
37
+ const method = cap.getPalette;
38
+ if (!isRecord$5(method) || typeof method.query !== "function") return false;
39
+ return true;
40
+ }
41
+ /** `getPalette` when the cap is mounted. Otherwise a rejection the painter logs. */
42
+ function readDisplayPalette(api) {
43
+ if (!isPaletteQueryApi(api)) return Promise.reject(/* @__PURE__ */ new Error("display-palette capability is not mounted"));
44
+ return api.displayPalette.getPalette.query();
45
+ }
46
+ function createDisplayPalettePainter(read, logger) {
47
+ let ready = require_clip_model_registry.bundledCamstack();
48
+ let announced = false;
49
+ let refreshing = false;
50
+ let fetchedAt = 0;
51
+ const say = (reason) => {
52
+ if (announced) return;
53
+ announced = true;
54
+ logger.warn("painting the bundled CamStack preset", { meta: { reason } });
55
+ };
56
+ const refresh = () => {
57
+ refreshing = true;
58
+ read().then((value) => {
59
+ const parsed = require_clip_model_registry.paletteResultSchema.safeParse(value);
60
+ if (!parsed.success) {
61
+ ready = require_clip_model_registry.bundledCamstack();
62
+ say("palette read did not match the schema");
63
+ return;
64
+ }
65
+ if (parsed.data.status === "unknown") {
66
+ ready = require_clip_model_registry.bundledCamstack();
67
+ say(parsed.data.reason);
68
+ return;
69
+ }
70
+ ready = parsed.data;
71
+ announced = false;
72
+ }).catch((err) => {
73
+ ready = require_clip_model_registry.bundledCamstack();
74
+ say(err instanceof Error ? err.message : String(err));
75
+ }).finally(() => {
76
+ fetchedAt = Date.now();
77
+ refreshing = false;
78
+ });
79
+ };
80
+ refresh();
81
+ const paint = (kind) => {
82
+ if (Date.now() - fetchedAt >= REFRESH_MS && !refreshing) refresh();
83
+ return require_clip_model_registry.paintHex(ready.swatches, ready.fallbacks, kind);
84
+ };
85
+ return { paint };
86
+ }
87
+ //#endregion
28
88
  //#region src/notification-center/alarm/alarm-mode-coverage.ts
29
89
  /**
30
90
  * Whether the panel just BECAME armed, in the sense a person means.
@@ -69174,6 +69234,7 @@ function isUsableBbox(bbox) {
69174
69234
  }
69175
69235
  //#endregion
69176
69236
  //#region src/pipeline-analytics/services/event-media-dispatcher.ts
69237
+ var BUNDLED_PALETTE$1 = require_clip_model_registry.bundledCamstack();
69177
69238
  /**
69178
69239
  * Long-side cap (px) for the boxed timeline tiles — `firstFrame`, `snapshot`,
69179
69240
  * `lastFrame`. These are the low-res "timeline filmstrip" images: a native full
@@ -69496,7 +69557,7 @@ var EventMediaDispatcher = class {
69496
69557
  lastFrameWritten: false
69497
69558
  };
69498
69559
  let scene = null;
69499
- if (sn.appendSnapshot || sn.rollingLastFrame) scene = await this.boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, sn.trackId, sn.bbox, sn.label);
69560
+ if (sn.appendSnapshot || sn.rollingLastFrame) scene = await this.boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, sn.trackId, sn.bbox, sn.label, sn.className);
69500
69561
  let stored = null;
69501
69562
  if (sn.appendSnapshot && scene) {
69502
69563
  await this.writeSceneTwin(deviceId, sn.trackId, sn.timestamp, scene.clean, "append");
@@ -69713,7 +69774,17 @@ var EventMediaDispatcher = class {
69713
69774
  * second fetch and no second decode (D654). `null` only if a sharp encode
69714
69775
  * throws.
69715
69776
  */
69716
- async boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, ownerId, bbox, label) {
69777
+ /** Stroke a timeline box in the class's palette colour. No class keeps the drawer's default. */
69778
+ paletteBox(box, className) {
69779
+ if (className === void 0 || className.length === 0) return box;
69780
+ const paint = this.deps.paintClass;
69781
+ const color = paint !== void 0 ? paint(className) : require_clip_model_registry.paintHex(BUNDLED_PALETTE$1.swatches, BUNDLED_PALETTE$1.fallbacks, className);
69782
+ return {
69783
+ ...box,
69784
+ color
69785
+ };
69786
+ }
69787
+ async boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, ownerId, bbox, label, className) {
69717
69788
  let nf = null;
69718
69789
  let nfJpeg = null;
69719
69790
  let fetchThrew = false;
@@ -69733,7 +69804,7 @@ var EventMediaDispatcher = class {
69733
69804
  }
69734
69805
  try {
69735
69806
  if (nfJpeg && nfJpeg.width > 0 && nfJpeg.height > 0) {
69736
- const box = scaleBox(bbox, fw, fh, nfJpeg.width, nfJpeg.height, label);
69807
+ const box = this.paletteBox(scaleBox(bbox, fw, fh, nfJpeg.width, nfJpeg.height, label), className);
69737
69808
  const opts = { quality: MEDIA_QUALITY };
69738
69809
  const [boxed, clean] = await Promise.all([drawBoxedJpeg(nfJpeg.jpeg, nfJpeg.width, nfJpeg.height, [box], opts), drawBoxedJpeg(nfJpeg.jpeg, nfJpeg.width, nfJpeg.height, [], opts)]);
69739
69810
  return {
@@ -69742,7 +69813,7 @@ var EventMediaDispatcher = class {
69742
69813
  };
69743
69814
  }
69744
69815
  if (nf && nf.format === "rgb" && nf.width > 0 && nf.height > 0) {
69745
- const box = scaleBox(bbox, fw, fh, nf.width, nf.height, label);
69816
+ const box = this.paletteBox(scaleBox(bbox, fw, fh, nf.width, nf.height, label), className);
69746
69817
  const opts = { quality: MEDIA_QUALITY };
69747
69818
  const [boxed, clean] = await Promise.all([drawBoxedFrame(nf.data, nf.width, nf.height, [box], opts), drawBoxedFrame(nf.data, nf.width, nf.height, [], opts)]);
69748
69819
  return {
@@ -69758,10 +69829,10 @@ var EventMediaDispatcher = class {
69758
69829
  shmId: frameHandle.shmId
69759
69830
  }
69760
69831
  });
69761
- const box = {
69832
+ const box = this.paletteBox({
69762
69833
  ...bbox,
69763
69834
  ...label ? { label } : {}
69764
- };
69835
+ }, className);
69765
69836
  const opts = {
69766
69837
  quality: MEDIA_QUALITY,
69767
69838
  maxWidth: SNAPSHOT_MAX_WIDTH
@@ -69834,7 +69905,7 @@ var EventMediaDispatcher = class {
69834
69905
  }
69835
69906
  }
69836
69907
  async writeTrackFrame(deviceId, frameHandle, frameData, fw, fh, tf) {
69837
- const scene = await this.boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, tf.trackId, tf.bbox, tf.label);
69908
+ const scene = await this.boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, tf.trackId, tf.bbox, tf.label, tf.className);
69838
69909
  if (!scene) return false;
69839
69910
  await this.writeSceneTwin(deviceId, tf.trackId, tf.timestamp, scene.clean, "append");
69840
69911
  try {
@@ -86938,6 +87009,14 @@ function toPixels(box, width, height) {
86938
87009
  h: Math.max(1, Math.min(Math.round(box.h * height), height - y))
86939
87010
  };
86940
87011
  }
87012
+ var BUNDLED_PALETTE = require_clip_model_registry.bundledCamstack();
87013
+ function bundledPaint(kind) {
87014
+ return require_clip_model_registry.paintHex(BUNDLED_PALETTE.swatches, BUNDLED_PALETTE.fallbacks, kind);
87015
+ }
87016
+ function boxStroke(box, paint) {
87017
+ if (box?.className !== void 0 && box.className.length > 0) return (paint ?? bundledPaint)(box.className);
87018
+ return box?.role === "other" ? NC_IMAGE_OTHER_COLOR : NC_IMAGE_SUBJECT_COLOR;
87019
+ }
86941
87020
  /** {@link notificationOverlay}'s SVG alone. */
86942
87021
  function notificationOverlaySvg(input) {
86943
87022
  return notificationOverlay(input).svg;
@@ -86959,9 +87038,10 @@ function notificationOverlay(input) {
86959
87038
  const points = zone.map((p) => `${String(clampPx(p.x * width, width))},${String(clampPx(p.y * height, height))}`).join(" ");
86960
87039
  parts.push(`<polygon data-role="zone" points="${points}" fill="${NC_IMAGE_ZONE_COLOR}" fill-opacity="0.18" stroke="${NC_IMAGE_ZONE_COLOR}" stroke-width="${String(strokes.other)}" stroke-dasharray="${String(strokes.subject * 2)},${String(strokes.subject)}"/>`);
86961
87040
  }
87041
+ const pathColor = boxStroke(input.boxes.find((b) => b.role === "subject"), input.paintClass);
86962
87042
  for (const run of input.paths ?? []) {
86963
87043
  if (run.length < 2) continue;
86964
- parts.push(`<polyline data-role="subject-path" points="${require_clip_model_registry.subjectPathSvgPoints(run, width, height)}" fill="none" stroke="${NC_IMAGE_SUBJECT_COLOR}" stroke-width="${String(strokes.subject)}" stroke-linejoin="round" stroke-linecap="round" stroke-opacity="0.9"/>`);
87044
+ parts.push(`<polyline data-role="subject-path" points="${require_clip_model_registry.subjectPathSvgPoints(run, width, height)}" fill="none" stroke="${pathColor}" stroke-width="${String(strokes.subject)}" stroke-linejoin="round" stroke-linecap="round" stroke-opacity="0.9"/>`);
86965
87045
  }
86966
87046
  const ordered = [...input.boxes.filter((b) => b.role === "other"), ...input.boxes.filter((b) => b.role === "subject")];
86967
87047
  const layout = layoutBoxLabels({
@@ -86973,7 +87053,7 @@ function notificationOverlay(input) {
86973
87053
  const plates = [];
86974
87054
  ordered.forEach((box, i) => {
86975
87055
  const subject = box.role === "subject";
86976
- const color = subject ? NC_IMAGE_SUBJECT_COLOR : NC_IMAGE_OTHER_COLOR;
87056
+ const color = boxStroke(box, input.paintClass);
86977
87057
  const stroke = subject ? strokes.subject : strokes.other;
86978
87058
  parts.push(`<rect data-role="${box.role}" x="${String(box.x)}" y="${String(box.y)}" width="${String(box.w)}" height="${String(box.h)}" fill="none" stroke="${color}" stroke-width="${String(stroke)}"/>`);
86979
87059
  const plate = layout.placements[i];
@@ -87142,11 +87222,13 @@ async function renderNotificationImage(req) {
87142
87222
  ...toPixels(o, outW, outH),
87143
87223
  role: "other",
87144
87224
  label: o.label,
87145
- ...o.confidence !== void 0 ? { score: o.confidence } : {}
87225
+ ...o.confidence !== void 0 ? { score: o.confidence } : {},
87226
+ ...o.className !== void 0 ? { className: o.className } : {}
87146
87227
  })), ...req.subject !== null ? [{
87147
87228
  ...toPixels(req.subject, outW, outH),
87148
87229
  role: "subject",
87149
- label: req.subject.label
87230
+ label: req.subject.label,
87231
+ ...req.subject.className !== void 0 ? { className: req.subject.className } : {}
87150
87232
  }] : []] : [];
87151
87233
  const zones = req.mode === "crop" ? [] : req.zones;
87152
87234
  const paths = require_clip_model_registry.projectSubjectPath(req.path ?? [], {
@@ -87167,7 +87249,8 @@ async function renderNotificationImage(req) {
87167
87249
  height: outH,
87168
87250
  boxes,
87169
87251
  zones,
87170
- paths
87252
+ paths,
87253
+ ...req.paintClass !== void 0 ? { paintClass: req.paintClass } : {}
87171
87254
  });
87172
87255
  if (boxes.length > 0) labels = overlay.labels;
87173
87256
  pipeline = pipeline.composite([{
@@ -87254,7 +87337,8 @@ var NcNotificationImageStage = class {
87254
87337
  const path = withPath ? this.subjectPath(input, trail) : [];
87255
87338
  const subject = subjectBox !== null ? {
87256
87339
  ...subjectBox,
87257
- label: imageLabelText(payload.subject.label ?? payload.subject.className, payload.subject.confidence)
87340
+ label: imageLabelText(payload.subject.label ?? payload.subject.className, payload.subject.confidence),
87341
+ className: payload.subject.className
87258
87342
  } : null;
87259
87343
  const othersDrawn = mode === "scene-boxes" ? otherTracks(await this.tracksAt(camera, source.timestamp), subjectTrackId, subjectBox, payload.subject.className) : [];
87260
87344
  if (mode === "scene-boxes") this.deps.logger.info("scene-boxes: other boxes drawn", {
@@ -87269,6 +87353,7 @@ var NcNotificationImageStage = class {
87269
87353
  const others = mode === "scene-boxes" ? othersDrawn.map((t) => ({
87270
87354
  ...t.bbox,
87271
87355
  label: imageLabelText(t.label ?? t.className, t.confidence),
87356
+ className: t.className,
87272
87357
  ...t.confidence !== void 0 ? { confidence: t.confidence } : {}
87273
87358
  })) : [];
87274
87359
  if (mode !== "crop" && input.withSubject && payload.mediaShowTriggerZone === true && payload.matchedZoneIds === void 0) this.deps.logger.info("trigger zone not drawn — the row never froze which zone fired", {
@@ -87287,7 +87372,8 @@ var NcNotificationImageStage = class {
87287
87372
  subject,
87288
87373
  others,
87289
87374
  zones,
87290
- ...path.length > 0 ? { path } : {}
87375
+ ...path.length > 0 ? { path } : {},
87376
+ ...this.deps.paintClass !== void 0 ? { paintClass: this.deps.paintClass } : {}
87291
87377
  });
87292
87378
  const reason = image.rendered === mode ? void 0 : mode === "crop" ? "no-subject-box" : "no-tracks-at-instant";
87293
87379
  if (reason !== void 0) this.reportFallback(input, mode, reason);
@@ -87620,7 +87706,8 @@ var NcDispatcher = class {
87620
87706
  now: this.now,
87621
87707
  ...deps.getSubjectTrail !== void 0 ? { getSubjectTrail: deps.getSubjectTrail } : {},
87622
87708
  ...deps.getTracksAt !== void 0 ? { getTracksAt: deps.getTracksAt } : {},
87623
- ...deps.getZonePolygons !== void 0 ? { getZonePolygons: deps.getZonePolygons } : {}
87709
+ ...deps.getZonePolygons !== void 0 ? { getZonePolygons: deps.getZonePolygons } : {},
87710
+ ...deps.paintClass !== void 0 ? { paintClass: deps.paintClass } : {}
87624
87711
  });
87625
87712
  }
87626
87713
  /**
@@ -109975,6 +110062,7 @@ var BuildNotificationCenter = class extends BuildNotificationCenterBase {
109975
110062
  y: pt.y
109976
110063
  })));
109977
110064
  },
110065
+ paintClass: createDisplayPalettePainter(() => readDisplayPalette(api), logger.child("DisplayPalette")).paint,
109978
110066
  renderEventMedia: (req) => this.renderEventMedia(req),
109979
110067
  cutRecordedClip: (req) => this.cutNotificationRecordedClip(req),
109980
110068
  deriveGifFromClip: (req) => deriveRecordedGif(buildRecordedGifPorts({
@@ -120526,7 +120614,8 @@ var SnapshotTargetPlanner = class {
120526
120614
  trackId: t.trackId,
120527
120615
  timestamp,
120528
120616
  bbox: firstFrameRetryBbox(t.bbox, this.trackStore?.peekActive(t.trackId)?.positions[0]?.bbox),
120529
- ...patchDisplayLabel(t.labelPatch) !== void 0 ? { label: patchDisplayLabel(t.labelPatch) } : {}
120617
+ ...patchDisplayLabel(t.labelPatch) !== void 0 ? { label: patchDisplayLabel(t.labelPatch) } : {},
120618
+ className: t.className
120530
120619
  });
120531
120620
  }
120532
120621
  return retries;
@@ -120724,6 +120813,7 @@ var SnapshotTargetPlanner = class {
120724
120813
  timestamp,
120725
120814
  bbox: { ...t.bbox },
120726
120815
  ...patchDisplayLabel(t.labelPatch) !== void 0 ? { label: patchDisplayLabel(t.labelPatch) } : {},
120816
+ className: t.className,
120727
120817
  appendSnapshot: plan.appendSnapshot,
120728
120818
  rollingLastFrame,
120729
120819
  bestThumbnail,
@@ -123155,6 +123245,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
123155
123245
  getParkedSubjectSlab: (deviceId, trackId) => this.mediaCapture.fetchParkedSubjectSlab(deviceId, trackId),
123156
123246
  mediaStore: stores.mediaStore,
123157
123247
  logger: logger.child("EventMediaDispatcher"),
123248
+ paintClass: createDisplayPalettePainter(() => readDisplayPalette(api), logger.child("DisplayPalette")).paint,
123158
123249
  onSubjectCropMiss: (deviceId, trackId, reason) => this.residents.notePreviewCaptureMiss(deviceId, trackId, `thumbnail:${reason}`)
123159
123250
  });
123160
123251
  this.buildRecognizers(api, logger, stores, transport);
@@ -1,4 +1,4 @@
1
- import { $ as MediaFileKindEnum, $i as RECORD_QUERY_MAX, $n as consumableFormOf, $t as OpsLogEntrySchema, A as DeclaredDevices, Ai as summarizeReview, An as TrackSideSchema, Ar as isDefaultAlarmProfileId, At as NcAlarmSensorsInputSchema, B as FULL_IMAGE_BBOX, Bi as viewerLinkBaseOf, Bn as applyModeDelaysEdits, Br as isScheduleActive, Bt as NcRuleUpdateInputSchema, C as ClearTrackRelationResultSchema, Ca as tuple, Ci as sensorRaisedOf, Cn as TimelapseRuleInputSchema, Cr as gifDeriveSpeed, Ct as NC_SNOOZE_MAX_MINUTES, D as DEFAULT_TIMELAPSE_PREVIEW_TEXT, Di as subKindsOf, Dn as TrackPuritySchema, Dr as isAlertEpisodeSeverity, Dt as NC_TEMPLATE_VARS, E as DEFAULT_EVENT_COLOR, Ea as EventCategory, Ei as storageOccupancyCapability, En as TrackPlacementSchema, Er as isAlertEpisodeOpen, Et as NC_TAXONOMY, F as EVENT_DENSITY_BATCH_MAX, Fi as systemEventSummaryScheduleOf, Fn as alarmPanelCapability, Fr as isKnownTemplateVar, Ft as NcRuleActionSchema, G as ListTrackRelationsResultSchema, Gi as evaluateSensorEdge, Gn as audioMetricsCapability, Gr as linkedStepOf, Gt as NcSnoozeSuppressedSchema, H as LABEL_SUPPLY_MACRO, Hi as zoneAnalyticsCapability, Hn as applySecureOnArmEdit, Hr as isSystemEventSummaryRule, Ht as NcSharedSequenceSchema, I as EVENT_KIND_BY_CAP, Ii as systemEventSummarySplitOf, In as alertEpisodeId, Ir as isLabelSupplyStepId, It as NcRuleInputSchema, J as MAX_BIRTH_DECISION_RECORDS, Ji as errMsg, Jn as buildSubjectPath, Jr as ncMediaPolicyError, Jt as NcTaxonomySchema, K as LockStateSchema, Ki as isSourceCap, Kn as audioModeOf, Kr as mayWriteToLocation, Kt as NcStateSummarySectionIdSchema, L as EVENT_OWNER_TYPES, Li as templateCarriesSummary, Ln as alertEpisodeKind, Lr as isMediaOwnerType, Lt as NcRulePatchSchema, M as EMBEDDING_MODEL_FAILED, Mi as systemEventDeliveryProblems, Mn as activateAlarmProfile, Mr as isDrawableSubjectPath, Mt as NcAlarmSettingsPatchSchema, N as EMBEDDING_REQUIREMENTS_FAILED, Ni as systemEventFamilyProblems, Nn as addonWidgetsSourceCapability, Nr as isEventKindLabelKey, Nt as NcConditionDescriptorSchema, O as DETECTION_MACRO_CLASSES, Oi as subjectPathSampleFromBox, On as TrackRelationKindSchema, Or as isAppLinkBase, Ot as NcAlarmConfigSchema, P as EMBEDDING_REQUIREMENTS_UNAVAILABLE, Pi as systemEventFilterApplies, Pn as alarmDeviceSecureOnArm, Pr as isEventOwnerType, Pt as NcConditionsSchema, Q as MOTION_CLOSE_AFTER_MS, Qi as RECORD_MAX_DATA_BYTES, Qn as cloneAlarmSettings, Qr as parseAlertEpisodePayload, Qt as OPS_LOG_DEFAULT_LIMIT, R as EXPORT_DENSE_MAX_RANGES, Ri as templateVarsFor, Rn as alertEpisodePayload, Rr as isRetiredClearKey, Rt as NcRuleSchema, S as ClearTrackRelationInputSchema, Sa as templateLiteral, Si as secureActuationFor, Sn as TRACK_RELATIONS_DEFAULT_LIMIT, Sr as failureContributionCapability, St as NC_SENSOR_TRANSITION_KINDS, T as DEFAULT_DETAIL_CROP_CONVENTION, Ta as unknown, Ti as startMoverUnderClearance, Tn as TimelapseRuleSchema, Tr as isAlarmControllableCap, Tt as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, U as LabelAttributionSchema, Ui as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, Un as armRemovalReconcile, Ur as isVectorIndexDimConflict, Ut as NcSnoozeInputSchema, V as FailureCounters, Vi as withSystemEventClasses, Vn as applyNonBlockingEdit, Vr as isSystemDelivery, Vt as NcScheduleSchema, W as ListTrackRelationsInputSchema, Wi as canonicalHash, Wn as assertTimelapseCadences, Wr as kebabToCamel, Wt as NcSnoozeSchema, X as MAX_TRACK_PURITIES, Xi as CamProfileSchema, Xn as calendarEventLocalSpan, Xr as notificationRulesCapability, Xt as NcTemplatePreviewSchema, Y as MAX_BIRTH_LATENCY_PROXY_MS, Yi as BaseAddon, Yn as buildViewerLink, Yr as normalizeNcMediaPolicy, Yt as NcTemplatePreviewInputSchema, Z as MAX_TRACK_RELATIONS, Zi as InvalidRecordError, Zn as classifyRetrainReview, Zr as occupancyScope, Zt as NcTemplateVarDescriptorSchema, _ as BIRTH_DECISION_DEFAULT_LIMIT, _a as object, _i as ruleBelongsToAlarm$1, _n as SceneMonitorSchema, _r as encodeVectorBase64, _t as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, a as CLIP_EMBEDDING_STEP_ID, aa as isDeviceScopedCap, ai as readMotionTriggeredBy, an as RetrainDismissedSchema, ar as deriveDetailCropRect, at as NC_ALARM_NOTIFY_FIELDS, b as BucketAccumulator, ba as strictObject, bi as ruleKindOf, bn as SetTrackRelationInputSchema, br as evictionPolicyOfLocation, bt as NC_GROUPING_MAX_SEC, c as readClusterModelPinStrict, ca as sleep$1, ci as resolveClipSearchMinScore, cn as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, cr as describeSystemEventDeliveryProblem, ct as NC_AUDIO_CONFIRM_HITS_DEFAULT, d as APPEARANCE_BLOCKS, da as array, di as resolveModeNotifyPolicy, dn as SCENE_DEFAULT_CHECK_INTERVAL_SEC, dr as deviceRemovalHookCapability, dt as NC_CLIP_PRE_ROLL_DEFAULT_SEC, ea as createEvent, ei as pickFaceRescoreIntervalMinutes, en as PackageLlmVerdictSchema, er as consumableLowPercentOf, et as MotionTriggeredBySchema, f as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, fa as boolean, fi as resolveNcMediaImage, fn as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, ft as NC_CLIP_RETENTION_MAX_SEC, g as ArchivedDebugNoteSchema, ga as number, gi as ruleAutoTriggersAlarm, gn as SCENE_RESET_RECAPTURES, gt as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, h as AlarmArmModeSchema, ha as looseObject, hi as rootSupplyServes, hn as SCENE_DIVERGED, ht as NC_CONFIRM_DEFAULT_TIMEOUT_MS, ia as hydrateSchema, ii as readDeviceStateFrom, in as RebuildObjectEmbeddingsRefusalSchema, ir as deleteAlarmProfile, it as NC_ALARM_DELAY_MAX_SEC, j as DetectionSourceSchema, ji as syncActiveAlarmProfileSettings, jn as TrackSourceSchema, jr as isDetectionMacroClass, jt as NcAlarmSensorsSchema, k as DETECTION_PIPELINE_CAP_NAME, ki as subjectPathSvgPoints, kn as TrackRelationSchema, kr as isAudioClassName, kt as NcAlarmPostTriggeredActionSchema, l as resolveClusterModelPin, la as ZodObject, li as resolveLocationMode, ln as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, lr as describeSystemEventFamilyProblem, lt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, m as AUDIO_MACRO_LABELS, ma as literal, mi as retrainRevisionConflictMessage, mn as SCENE_DEFAULT_UNCOVERED_POLICY, mr as embeddingRefusalOf, mt as NC_CONFIRM_DEFAULT_MAX_IMAGE_PX, na as defineCustomActions, ni as plateGalleryCapability, nn as RECORDING_EXPORT_MAX_READ_BYTES, nr as cosineSimilarity$1, nt as NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC, o as CLUSTER_MODEL_OWNER_ADDON_ID, oa as nodePin, oi as readTimelapseGeneratedAt, on as RetrainOriginSchema, or as derivePostTriggeredAction, ot as NC_ALARM_SYSTEM_EVENT_KINDS, p as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, pa as discriminatedUnion, pn as SCENE_DEFAULT_QUIET_SECONDS, pt as NC_CONDITION_CATALOG, q as MAX_ARCHIVED_DEBUG_NOTES, qi as DeviceType, qn as buildEventKindDescriptor, qr as memoizePinnedFfmpeg, qt as NcSystemEventKindSchema, ra as defineRecordKinds, ri as projectSubjectPath, rn as RECORDING_SOURCE_CAMSTACK_ADDON, rr as createAlarmProfile, rt as NC_ALARM_DELAY_FIELDS, s as FACE_EMBEDDING_STEP_ID, si as renameAlarmProfile, sn as RetrainStatusSchema, sr as deriveRecordingMode, st as NC_ALARM_TRIGGERED_MAX_SEC, t as BUILTIN_CLIP_MODELS, ta as customAction, ti as pipelineAnalyticsCapability, tr as coreBlockIdFromAddonId, tt as NC_ALARM_DEFAULT_PROFILE_ID, u as APPEARANCE_BIN_COUNT, ua as _enum, ui as resolveModeDelays, un as SCENE_DEFAULT_ANCHOR_THRESHOLD, ur as deviceAttentionKind, ut as NC_CLIP_POST_ROLL_DEFAULT_SEC, v as BaseDevice, va as partialRecord, vi as ruleDeviceCompatCapQueries, vn as SetTrackPurityInputSchema, vr as ensureAlarmProfiles, vt as NC_DEFAULT_SNOOZE_MINUTES, w as CoverStateSchema, wa as union, wi as servedTemplateVars, wn as TimelapseRulePatchSchema, wr as gifFromMp4Args, wt as NC_STATE_SUMMARY_SECTION_IDS, x as COCO_TO_MACRO, xa as string, xi as sceneMonitorCapability, xn as TIMELAPSE_DENSE_FLOOR_SEC, xr as faceGalleryCapability, xt as NC_GROUPING_MIN_SEC, y as BirthDecisionRecordSchema, ya as record, yi as ruleGroupingApplies, yn as SetTrackPurityResultSchema, yr as eventKindLabel, yt as NC_GROUPING_DEFAULT_SEC, z as FIRST_LEVEL_MACRO_CLASSES, zi as vectorDimFromBase64, zn as applyBlockingEdit, zr as isRootSuppliableStepId, zt as NcRuleTargetSchema } from "../clip-model-registry-0ayA23hb.mjs";
1
+ import { $ as MediaFileKindEnum, $i as CamProfileSchema, $n as cloneAlarmSettings, $r as paintHex, $t as OpsLogEntrySchema, A as DeclaredDevices, Ai as subKindsOf, An as TrackSideSchema, Ar as isAudioClassName, At as NcAlarmSensorsInputSchema, B as FULL_IMAGE_BBOX, Bi as templateCarriesSummary, Bn as applyModeDelaysEdits, Br as isRootSuppliableStepId, Bt as NcRuleUpdateInputSchema, C as ClearTrackRelationResultSchema, Ca as strictObject, Ci as ruleKindOf, Cn as TimelapseRuleInputSchema, Cr as failureContributionCapability, Ct as NC_SNOOZE_MAX_MINUTES, D as DEFAULT_TIMELAPSE_PREVIEW_TEXT, Da as union, Di as servedTemplateVars, Dn as TrackPuritySchema, Dr as isAlertEpisodeOpen, Dt as NC_TEMPLATE_VARS, E as DEFAULT_EVENT_COLOR, Ea as tuple, Ei as sensorRaisedOf, En as TrackPlacementSchema, Er as isAlarmControllableCap, Et as NC_TAXONOMY, F as EVENT_DENSITY_BATCH_MAX, Fi as systemEventDeliveryProblems, Fn as alarmPanelCapability, Fr as isEventOwnerType, Ft as NcRuleActionSchema, G as ListTrackRelationsResultSchema, Gi as zoneAnalyticsCapability, Gn as audioMetricsCapability, Gr as kebabToCamel, Gt as NcSnoozeSuppressedSchema, H as LABEL_SUPPLY_MACRO, Hi as vectorDimFromBase64, Hn as applySecureOnArmEdit, Hr as isSystemDelivery, Ht as NcSharedSequenceSchema, I as EVENT_KIND_BY_CAP, Ii as systemEventFamilyProblems, In as alertEpisodeId, Ir as isKnownTemplateVar, It as NcRuleInputSchema, J as MAX_BIRTH_DECISION_RECORDS, Ji as evaluateSensorEdge, Jn as buildSubjectPath, Jr as memoizePinnedFfmpeg, Jt as NcTaxonomySchema, K as LockStateSchema, Ki as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, Kn as audioModeOf, Kr as linkedStepOf, Kt as NcStateSummarySectionIdSchema, L as EVENT_OWNER_TYPES, Li as systemEventFilterApplies, Ln as alertEpisodeKind, Lr as isLabelSupplyStepId, Lt as NcRulePatchSchema, M as EMBEDDING_MODEL_FAILED, Mi as subjectPathSvgPoints, Mn as activateAlarmProfile, Mr as isDetectionMacroClass, Mt as NcAlarmSettingsPatchSchema, N as EMBEDDING_REQUIREMENTS_FAILED, Ni as summarizeReview, Nn as addonWidgetsSourceCapability, Nr as isDrawableSubjectPath, Nt as NcConditionDescriptorSchema, O as DETECTION_MACRO_CLASSES, Oa as unknown, Oi as startMoverUnderClearance, On as TrackRelationKindSchema, Or as isAlertEpisodeSeverity, Ot as NcAlarmConfigSchema, P as EMBEDDING_REQUIREMENTS_UNAVAILABLE, Pi as syncActiveAlarmProfileSettings, Pn as alarmDeviceSecureOnArm, Pr as isEventKindLabelKey, Pt as NcConditionsSchema, Q as MOTION_CLOSE_AFTER_MS, Qi as BaseAddon, Qn as classifyRetrainReview, Qr as occupancyScope, Qt as OPS_LOG_DEFAULT_LIMIT, R as EXPORT_DENSE_MAX_RANGES, Ri as systemEventSummaryScheduleOf, Rn as alertEpisodePayload, Rr as isMediaOwnerType, Rt as NcRuleSchema, S as ClearTrackRelationInputSchema, Sa as record, Si as ruleGroupingApplies, Sn as TRACK_RELATIONS_DEFAULT_LIMIT, Sr as faceGalleryCapability, St as NC_SENSOR_TRANSITION_KINDS, T as DEFAULT_DETAIL_CROP_CONVENTION, Ta as templateLiteral, Ti as secureActuationFor, Tn as TimelapseRuleSchema, Tr as gifFromMp4Args, Tt as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, U as LabelAttributionSchema, Ui as viewerLinkBaseOf, Un as armRemovalReconcile, Ur as isSystemEventSummaryRule, Ut as NcSnoozeInputSchema, V as FailureCounters, Vi as templateVarsFor, Vn as applyNonBlockingEdit, Vr as isScheduleActive, Vt as NcScheduleSchema, W as ListTrackRelationsInputSchema, Wi as withSystemEventClasses, Wn as assertTimelapseCadences, Wr as isVectorIndexDimConflict, Wt as NcSnoozeSchema, X as MAX_TRACK_PURITIES, Xi as DeviceType, Xn as bundledCamstack, Xr as normalizeNcMediaPolicy, Xt as NcTemplatePreviewSchema, Y as MAX_BIRTH_LATENCY_PROXY_MS, Yi as isSourceCap, Yn as buildViewerLink, Yr as ncMediaPolicyError, Yt as NcTemplatePreviewInputSchema, Z as MAX_TRACK_RELATIONS, Zi as errMsg, Zn as calendarEventLocalSpan, Zr as notificationRulesCapability, Zt as NcTemplateVarDescriptorSchema, _ as BIRTH_DECISION_DEFAULT_LIMIT, _a as literal, _i as retrainRevisionConflictMessage, _n as SceneMonitorSchema, _t as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, a as CLIP_EMBEDDING_STEP_ID, aa as defineCustomActions, ai as plateGalleryCapability, an as RetrainDismissedSchema, ar as deleteAlarmProfile, at as NC_ALARM_NOTIFY_FIELDS, b as BucketAccumulator, ba as object, bi as ruleBelongsToAlarm$1, bn as SetTrackRelationInputSchema, br as eventKindLabel, bt as NC_GROUPING_MAX_SEC, c as readClusterModelPinStrict, ca as isDeviceScopedCap, ci as readMotionTriggeredBy, cn as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, cr as deriveRecordingMode, ct as NC_AUDIO_CONFIRM_HITS_DEFAULT, d as APPEARANCE_BLOCKS, da as sleep$1, di as resolveClipSearchMinScore, dn as SCENE_DEFAULT_CHECK_INTERVAL_SEC, dr as deviceAttentionKind, dt as NC_CLIP_PRE_ROLL_DEFAULT_SEC, ea as InvalidRecordError, ei as paletteResultSchema, en as PackageLlmVerdictSchema, er as consumableFormOf, et as MotionTriggeredBySchema, f as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, fa as ZodObject, fi as resolveLocationMode, fn as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, fr as deviceRemovalHookCapability, ft as NC_CLIP_RETENTION_MAX_SEC, g as ArchivedDebugNoteSchema, ga as discriminatedUnion, gn as SCENE_RESET_RECAPTURES, gt as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, h as AlarmArmModeSchema, ha as boolean, hi as resolveNcMediaImage, hn as SCENE_DIVERGED, hr as embeddingRefusalOf, ht as NC_CONFIRM_DEFAULT_TIMEOUT_MS, ia as customAction, ii as pipelineAnalyticsCapability, in as RebuildObjectEmbeddingsRefusalSchema, ir as createAlarmProfile, it as NC_ALARM_DELAY_MAX_SEC, j as DetectionSourceSchema, ji as subjectPathSampleFromBox, jn as TrackSourceSchema, jr as isDefaultAlarmProfileId, jt as NcAlarmSensorsSchema, k as DETECTION_PIPELINE_CAP_NAME, ka as EventCategory, ki as storageOccupancyCapability, kn as TrackRelationSchema, kr as isAppLinkBase, kt as NcAlarmPostTriggeredActionSchema, l as resolveClusterModelPin, la as nodePin, li as readTimelapseGeneratedAt, ln as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, lr as describeSystemEventDeliveryProblem, lt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, m as AUDIO_MACRO_LABELS, ma as array, mi as resolveModeNotifyPolicy, mn as SCENE_DEFAULT_UNCOVERED_POLICY, mt as NC_CONFIRM_DEFAULT_MAX_IMAGE_PX, na as RECORD_QUERY_MAX, nn as RECORDING_EXPORT_MAX_READ_BYTES, nr as coreBlockIdFromAddonId, nt as NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC, o as CLUSTER_MODEL_OWNER_ADDON_ID, oa as defineRecordKinds, oi as projectSubjectPath, on as RetrainOriginSchema, or as deriveDetailCropRect, ot as NC_ALARM_SYSTEM_EVENT_KINDS, p as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, pa as _enum, pi as resolveModeDelays, pn as SCENE_DEFAULT_QUIET_SECONDS, pt as NC_CONDITION_CATALOG, q as MAX_ARCHIVED_DEBUG_NOTES, qi as canonicalHash, qn as buildEventKindDescriptor, qr as mayWriteToLocation, qt as NcSystemEventKindSchema, ra as createEvent, ri as pickFaceRescoreIntervalMinutes, rn as RECORDING_SOURCE_CAMSTACK_ADDON, rr as cosineSimilarity$1, rt as NC_ALARM_DELAY_FIELDS, s as FACE_EMBEDDING_STEP_ID, sa as hydrateSchema, si as readDeviceStateFrom, sn as RetrainStatusSchema, sr as derivePostTriggeredAction, st as NC_ALARM_TRIGGERED_MAX_SEC, t as BUILTIN_CLIP_MODELS, ta as RECORD_MAX_DATA_BYTES, ti as parseAlertEpisodePayload, tr as consumableLowPercentOf, tt as NC_ALARM_DEFAULT_PROFILE_ID, u as APPEARANCE_BIN_COUNT, ui as renameAlarmProfile, un as SCENE_DEFAULT_ANCHOR_THRESHOLD, ur as describeSystemEventFamilyProblem, ut as NC_CLIP_POST_ROLL_DEFAULT_SEC, v as BaseDevice, va as looseObject, vi as rootSupplyServes, vn as SetTrackPurityInputSchema, vr as encodeVectorBase64, vt as NC_DEFAULT_SNOOZE_MINUTES, w as CoverStateSchema, wa as string, wi as sceneMonitorCapability, wn as TimelapseRulePatchSchema, wr as gifDeriveSpeed, wt as NC_STATE_SUMMARY_SECTION_IDS, x as COCO_TO_MACRO, xa as partialRecord, xi as ruleDeviceCompatCapQueries, xn as TIMELAPSE_DENSE_FLOOR_SEC, xr as evictionPolicyOfLocation, xt as NC_GROUPING_MIN_SEC, y as BirthDecisionRecordSchema, ya as number, yi as ruleAutoTriggersAlarm, yn as SetTrackPurityResultSchema, yr as ensureAlarmProfiles, yt as NC_GROUPING_DEFAULT_SEC, z as FIRST_LEVEL_MACRO_CLASSES, zi as systemEventSummarySplitOf, zn as applyBlockingEdit, zr as isRetiredClearKey, zt as NcRuleTargetSchema } from "../clip-model-registry-CCbbEBYS.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";
@@ -18,6 +18,66 @@ import { request } from "node:http";
18
18
  import { request as request$1 } from "node:https";
19
19
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
20
20
  import { Buffer as Buffer$1 } from "node:buffer";
21
+ //#region src/shared/display-palette-painter.ts
22
+ var REFRESH_MS = 3e4;
23
+ function isRecord$5(value) {
24
+ return typeof value === "object" && value !== null;
25
+ }
26
+ function isPaletteQueryApi(value) {
27
+ if (!("displayPalette" in value)) return false;
28
+ const cap = value.displayPalette;
29
+ if (!isRecord$5(cap) || !("getPalette" in cap)) return false;
30
+ const method = cap.getPalette;
31
+ if (!isRecord$5(method) || typeof method.query !== "function") return false;
32
+ return true;
33
+ }
34
+ /** `getPalette` when the cap is mounted. Otherwise a rejection the painter logs. */
35
+ function readDisplayPalette(api) {
36
+ if (!isPaletteQueryApi(api)) return Promise.reject(/* @__PURE__ */ new Error("display-palette capability is not mounted"));
37
+ return api.displayPalette.getPalette.query();
38
+ }
39
+ function createDisplayPalettePainter(read, logger) {
40
+ let ready = bundledCamstack();
41
+ let announced = false;
42
+ let refreshing = false;
43
+ let fetchedAt = 0;
44
+ const say = (reason) => {
45
+ if (announced) return;
46
+ announced = true;
47
+ logger.warn("painting the bundled CamStack preset", { meta: { reason } });
48
+ };
49
+ const refresh = () => {
50
+ refreshing = true;
51
+ read().then((value) => {
52
+ const parsed = paletteResultSchema.safeParse(value);
53
+ if (!parsed.success) {
54
+ ready = bundledCamstack();
55
+ say("palette read did not match the schema");
56
+ return;
57
+ }
58
+ if (parsed.data.status === "unknown") {
59
+ ready = bundledCamstack();
60
+ say(parsed.data.reason);
61
+ return;
62
+ }
63
+ ready = parsed.data;
64
+ announced = false;
65
+ }).catch((err) => {
66
+ ready = bundledCamstack();
67
+ say(err instanceof Error ? err.message : String(err));
68
+ }).finally(() => {
69
+ fetchedAt = Date.now();
70
+ refreshing = false;
71
+ });
72
+ };
73
+ refresh();
74
+ const paint = (kind) => {
75
+ if (Date.now() - fetchedAt >= REFRESH_MS && !refreshing) refresh();
76
+ return paintHex(ready.swatches, ready.fallbacks, kind);
77
+ };
78
+ return { paint };
79
+ }
80
+ //#endregion
21
81
  //#region src/notification-center/alarm/alarm-mode-coverage.ts
22
82
  /**
23
83
  * Whether the panel just BECAME armed, in the sense a person means.
@@ -69079,6 +69139,7 @@ function isUsableBbox(bbox) {
69079
69139
  }
69080
69140
  //#endregion
69081
69141
  //#region src/pipeline-analytics/services/event-media-dispatcher.ts
69142
+ var BUNDLED_PALETTE$1 = bundledCamstack();
69082
69143
  /**
69083
69144
  * Long-side cap (px) for the boxed timeline tiles — `firstFrame`, `snapshot`,
69084
69145
  * `lastFrame`. These are the low-res "timeline filmstrip" images: a native full
@@ -69401,7 +69462,7 @@ var EventMediaDispatcher = class {
69401
69462
  lastFrameWritten: false
69402
69463
  };
69403
69464
  let scene = null;
69404
- if (sn.appendSnapshot || sn.rollingLastFrame) scene = await this.boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, sn.trackId, sn.bbox, sn.label);
69465
+ if (sn.appendSnapshot || sn.rollingLastFrame) scene = await this.boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, sn.trackId, sn.bbox, sn.label, sn.className);
69405
69466
  let stored = null;
69406
69467
  if (sn.appendSnapshot && scene) {
69407
69468
  await this.writeSceneTwin(deviceId, sn.trackId, sn.timestamp, scene.clean, "append");
@@ -69618,7 +69679,17 @@ var EventMediaDispatcher = class {
69618
69679
  * second fetch and no second decode (D654). `null` only if a sharp encode
69619
69680
  * throws.
69620
69681
  */
69621
- async boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, ownerId, bbox, label) {
69682
+ /** Stroke a timeline box in the class's palette colour. No class keeps the drawer's default. */
69683
+ paletteBox(box, className) {
69684
+ if (className === void 0 || className.length === 0) return box;
69685
+ const paint = this.deps.paintClass;
69686
+ const color = paint !== void 0 ? paint(className) : paintHex(BUNDLED_PALETTE$1.swatches, BUNDLED_PALETTE$1.fallbacks, className);
69687
+ return {
69688
+ ...box,
69689
+ color
69690
+ };
69691
+ }
69692
+ async boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, ownerId, bbox, label, className) {
69622
69693
  let nf = null;
69623
69694
  let nfJpeg = null;
69624
69695
  let fetchThrew = false;
@@ -69638,7 +69709,7 @@ var EventMediaDispatcher = class {
69638
69709
  }
69639
69710
  try {
69640
69711
  if (nfJpeg && nfJpeg.width > 0 && nfJpeg.height > 0) {
69641
- const box = scaleBox(bbox, fw, fh, nfJpeg.width, nfJpeg.height, label);
69712
+ const box = this.paletteBox(scaleBox(bbox, fw, fh, nfJpeg.width, nfJpeg.height, label), className);
69642
69713
  const opts = { quality: MEDIA_QUALITY };
69643
69714
  const [boxed, clean] = await Promise.all([drawBoxedJpeg(nfJpeg.jpeg, nfJpeg.width, nfJpeg.height, [box], opts), drawBoxedJpeg(nfJpeg.jpeg, nfJpeg.width, nfJpeg.height, [], opts)]);
69644
69715
  return {
@@ -69647,7 +69718,7 @@ var EventMediaDispatcher = class {
69647
69718
  };
69648
69719
  }
69649
69720
  if (nf && nf.format === "rgb" && nf.width > 0 && nf.height > 0) {
69650
- const box = scaleBox(bbox, fw, fh, nf.width, nf.height, label);
69721
+ const box = this.paletteBox(scaleBox(bbox, fw, fh, nf.width, nf.height, label), className);
69651
69722
  const opts = { quality: MEDIA_QUALITY };
69652
69723
  const [boxed, clean] = await Promise.all([drawBoxedFrame(nf.data, nf.width, nf.height, [box], opts), drawBoxedFrame(nf.data, nf.width, nf.height, [], opts)]);
69653
69724
  return {
@@ -69663,10 +69734,10 @@ var EventMediaDispatcher = class {
69663
69734
  shmId: frameHandle.shmId
69664
69735
  }
69665
69736
  });
69666
- const box = {
69737
+ const box = this.paletteBox({
69667
69738
  ...bbox,
69668
69739
  ...label ? { label } : {}
69669
- };
69740
+ }, className);
69670
69741
  const opts = {
69671
69742
  quality: MEDIA_QUALITY,
69672
69743
  maxWidth: SNAPSHOT_MAX_WIDTH
@@ -69739,7 +69810,7 @@ var EventMediaDispatcher = class {
69739
69810
  }
69740
69811
  }
69741
69812
  async writeTrackFrame(deviceId, frameHandle, frameData, fw, fh, tf) {
69742
- const scene = await this.boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, tf.trackId, tf.bbox, tf.label);
69813
+ const scene = await this.boxedTimelineFrame(deviceId, frameHandle, frameData, fw, fh, tf.trackId, tf.bbox, tf.label, tf.className);
69743
69814
  if (!scene) return false;
69744
69815
  await this.writeSceneTwin(deviceId, tf.trackId, tf.timestamp, scene.clean, "append");
69745
69816
  try {
@@ -86843,6 +86914,14 @@ function toPixels(box, width, height) {
86843
86914
  h: Math.max(1, Math.min(Math.round(box.h * height), height - y))
86844
86915
  };
86845
86916
  }
86917
+ var BUNDLED_PALETTE = bundledCamstack();
86918
+ function bundledPaint(kind) {
86919
+ return paintHex(BUNDLED_PALETTE.swatches, BUNDLED_PALETTE.fallbacks, kind);
86920
+ }
86921
+ function boxStroke(box, paint) {
86922
+ if (box?.className !== void 0 && box.className.length > 0) return (paint ?? bundledPaint)(box.className);
86923
+ return box?.role === "other" ? NC_IMAGE_OTHER_COLOR : NC_IMAGE_SUBJECT_COLOR;
86924
+ }
86846
86925
  /** {@link notificationOverlay}'s SVG alone. */
86847
86926
  function notificationOverlaySvg(input) {
86848
86927
  return notificationOverlay(input).svg;
@@ -86864,9 +86943,10 @@ function notificationOverlay(input) {
86864
86943
  const points = zone.map((p) => `${String(clampPx(p.x * width, width))},${String(clampPx(p.y * height, height))}`).join(" ");
86865
86944
  parts.push(`<polygon data-role="zone" points="${points}" fill="${NC_IMAGE_ZONE_COLOR}" fill-opacity="0.18" stroke="${NC_IMAGE_ZONE_COLOR}" stroke-width="${String(strokes.other)}" stroke-dasharray="${String(strokes.subject * 2)},${String(strokes.subject)}"/>`);
86866
86945
  }
86946
+ const pathColor = boxStroke(input.boxes.find((b) => b.role === "subject"), input.paintClass);
86867
86947
  for (const run of input.paths ?? []) {
86868
86948
  if (run.length < 2) continue;
86869
- parts.push(`<polyline data-role="subject-path" points="${subjectPathSvgPoints(run, width, height)}" fill="none" stroke="${NC_IMAGE_SUBJECT_COLOR}" stroke-width="${String(strokes.subject)}" stroke-linejoin="round" stroke-linecap="round" stroke-opacity="0.9"/>`);
86949
+ parts.push(`<polyline data-role="subject-path" points="${subjectPathSvgPoints(run, width, height)}" fill="none" stroke="${pathColor}" stroke-width="${String(strokes.subject)}" stroke-linejoin="round" stroke-linecap="round" stroke-opacity="0.9"/>`);
86870
86950
  }
86871
86951
  const ordered = [...input.boxes.filter((b) => b.role === "other"), ...input.boxes.filter((b) => b.role === "subject")];
86872
86952
  const layout = layoutBoxLabels({
@@ -86878,7 +86958,7 @@ function notificationOverlay(input) {
86878
86958
  const plates = [];
86879
86959
  ordered.forEach((box, i) => {
86880
86960
  const subject = box.role === "subject";
86881
- const color = subject ? NC_IMAGE_SUBJECT_COLOR : NC_IMAGE_OTHER_COLOR;
86961
+ const color = boxStroke(box, input.paintClass);
86882
86962
  const stroke = subject ? strokes.subject : strokes.other;
86883
86963
  parts.push(`<rect data-role="${box.role}" x="${String(box.x)}" y="${String(box.y)}" width="${String(box.w)}" height="${String(box.h)}" fill="none" stroke="${color}" stroke-width="${String(stroke)}"/>`);
86884
86964
  const plate = layout.placements[i];
@@ -87047,11 +87127,13 @@ async function renderNotificationImage(req) {
87047
87127
  ...toPixels(o, outW, outH),
87048
87128
  role: "other",
87049
87129
  label: o.label,
87050
- ...o.confidence !== void 0 ? { score: o.confidence } : {}
87130
+ ...o.confidence !== void 0 ? { score: o.confidence } : {},
87131
+ ...o.className !== void 0 ? { className: o.className } : {}
87051
87132
  })), ...req.subject !== null ? [{
87052
87133
  ...toPixels(req.subject, outW, outH),
87053
87134
  role: "subject",
87054
- label: req.subject.label
87135
+ label: req.subject.label,
87136
+ ...req.subject.className !== void 0 ? { className: req.subject.className } : {}
87055
87137
  }] : []] : [];
87056
87138
  const zones = req.mode === "crop" ? [] : req.zones;
87057
87139
  const paths = projectSubjectPath(req.path ?? [], {
@@ -87072,7 +87154,8 @@ async function renderNotificationImage(req) {
87072
87154
  height: outH,
87073
87155
  boxes,
87074
87156
  zones,
87075
- paths
87157
+ paths,
87158
+ ...req.paintClass !== void 0 ? { paintClass: req.paintClass } : {}
87076
87159
  });
87077
87160
  if (boxes.length > 0) labels = overlay.labels;
87078
87161
  pipeline = pipeline.composite([{
@@ -87159,7 +87242,8 @@ var NcNotificationImageStage = class {
87159
87242
  const path = withPath ? this.subjectPath(input, trail) : [];
87160
87243
  const subject = subjectBox !== null ? {
87161
87244
  ...subjectBox,
87162
- label: imageLabelText(payload.subject.label ?? payload.subject.className, payload.subject.confidence)
87245
+ label: imageLabelText(payload.subject.label ?? payload.subject.className, payload.subject.confidence),
87246
+ className: payload.subject.className
87163
87247
  } : null;
87164
87248
  const othersDrawn = mode === "scene-boxes" ? otherTracks(await this.tracksAt(camera, source.timestamp), subjectTrackId, subjectBox, payload.subject.className) : [];
87165
87249
  if (mode === "scene-boxes") this.deps.logger.info("scene-boxes: other boxes drawn", {
@@ -87174,6 +87258,7 @@ var NcNotificationImageStage = class {
87174
87258
  const others = mode === "scene-boxes" ? othersDrawn.map((t) => ({
87175
87259
  ...t.bbox,
87176
87260
  label: imageLabelText(t.label ?? t.className, t.confidence),
87261
+ className: t.className,
87177
87262
  ...t.confidence !== void 0 ? { confidence: t.confidence } : {}
87178
87263
  })) : [];
87179
87264
  if (mode !== "crop" && input.withSubject && payload.mediaShowTriggerZone === true && payload.matchedZoneIds === void 0) this.deps.logger.info("trigger zone not drawn — the row never froze which zone fired", {
@@ -87192,7 +87277,8 @@ var NcNotificationImageStage = class {
87192
87277
  subject,
87193
87278
  others,
87194
87279
  zones,
87195
- ...path.length > 0 ? { path } : {}
87280
+ ...path.length > 0 ? { path } : {},
87281
+ ...this.deps.paintClass !== void 0 ? { paintClass: this.deps.paintClass } : {}
87196
87282
  });
87197
87283
  const reason = image.rendered === mode ? void 0 : mode === "crop" ? "no-subject-box" : "no-tracks-at-instant";
87198
87284
  if (reason !== void 0) this.reportFallback(input, mode, reason);
@@ -87525,7 +87611,8 @@ var NcDispatcher = class {
87525
87611
  now: this.now,
87526
87612
  ...deps.getSubjectTrail !== void 0 ? { getSubjectTrail: deps.getSubjectTrail } : {},
87527
87613
  ...deps.getTracksAt !== void 0 ? { getTracksAt: deps.getTracksAt } : {},
87528
- ...deps.getZonePolygons !== void 0 ? { getZonePolygons: deps.getZonePolygons } : {}
87614
+ ...deps.getZonePolygons !== void 0 ? { getZonePolygons: deps.getZonePolygons } : {},
87615
+ ...deps.paintClass !== void 0 ? { paintClass: deps.paintClass } : {}
87529
87616
  });
87530
87617
  }
87531
87618
  /**
@@ -109880,6 +109967,7 @@ var BuildNotificationCenter = class extends BuildNotificationCenterBase {
109880
109967
  y: pt.y
109881
109968
  })));
109882
109969
  },
109970
+ paintClass: createDisplayPalettePainter(() => readDisplayPalette(api), logger.child("DisplayPalette")).paint,
109883
109971
  renderEventMedia: (req) => this.renderEventMedia(req),
109884
109972
  cutRecordedClip: (req) => this.cutNotificationRecordedClip(req),
109885
109973
  deriveGifFromClip: (req) => deriveRecordedGif(buildRecordedGifPorts({
@@ -120431,7 +120519,8 @@ var SnapshotTargetPlanner = class {
120431
120519
  trackId: t.trackId,
120432
120520
  timestamp,
120433
120521
  bbox: firstFrameRetryBbox(t.bbox, this.trackStore?.peekActive(t.trackId)?.positions[0]?.bbox),
120434
- ...patchDisplayLabel(t.labelPatch) !== void 0 ? { label: patchDisplayLabel(t.labelPatch) } : {}
120522
+ ...patchDisplayLabel(t.labelPatch) !== void 0 ? { label: patchDisplayLabel(t.labelPatch) } : {},
120523
+ className: t.className
120435
120524
  });
120436
120525
  }
120437
120526
  return retries;
@@ -120629,6 +120718,7 @@ var SnapshotTargetPlanner = class {
120629
120718
  timestamp,
120630
120719
  bbox: { ...t.bbox },
120631
120720
  ...patchDisplayLabel(t.labelPatch) !== void 0 ? { label: patchDisplayLabel(t.labelPatch) } : {},
120721
+ className: t.className,
120632
120722
  appendSnapshot: plan.appendSnapshot,
120633
120723
  rollingLastFrame,
120634
120724
  bestThumbnail,
@@ -123060,6 +123150,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
123060
123150
  getParkedSubjectSlab: (deviceId, trackId) => this.mediaCapture.fetchParkedSubjectSlab(deviceId, trackId),
123061
123151
  mediaStore: stores.mediaStore,
123062
123152
  logger: logger.child("EventMediaDispatcher"),
123153
+ paintClass: createDisplayPalettePainter(() => readDisplayPalette(api), logger.child("DisplayPalette")).paint,
123063
123154
  onSubjectCropMiss: (deviceId, trackId, reason) => this.residents.notePreviewCaptureMiss(deviceId, trackId, `thumbnail:${reason}`)
123064
123155
  });
123065
123156
  this.buildRecognizers(api, logger, stores, transport);
@@ -30,7 +30,7 @@ async function d(e) {
30
30
  }
31
31
  }
32
32
  async function f() {
33
- return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-HmQ3SInG.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-ArpdWsMY.mjs")).catch((e) => {
34
34
  throw l = void 0, e;
35
35
  }), l;
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-post-analysis",
3
- "version": "1.2.632",
3
+ "version": "1.2.633",
4
4
  "description": "Post-Analysis bundle — enrichment, embedding-encoder, pipeline-analytics. Multi-entry npm package shipping addons that consume pipeline output.",
5
5
  "keywords": [
6
6
  "camstack",